无敌:神策杯 2018高校算法大师赛(个人、top2、top6)方案总结

优采云 发布时间: 2022-10-07 02:07

  无敌:神策杯 2018高校算法大师赛(个人、top2、top6)方案总结

  Sensors数据推荐系统是基于Sensors分析平台的智能推荐系统。根据客户需求和业务特点,基于Sensors Analysis采集的用户行为数据,利用机器学习算法对咨询、视频、产品进行个性化推荐,为客户提供不同场景下的智能应用,如优化产品体验,提升点击率等核心业务指标。

  Sensors 推荐系统是一个完整的学习闭环。采集的基础数据是通过机器学习的算法模型来应用的。实时验证效果,从而指导数据源的添加,算法优化反馈形成全流程、实时、自动、快速迭代的推荐闭环。

  本次比赛为模拟商业场景,目的是提取新闻文本的核心词,最终的结果将达到提升推荐和用户画像的效果。

  比赛链接:

  数据集数据地址:

  密码:qa2u

  02 使命

  个性化推荐系统是Sensors智能系统的一个重要方面。准确理解信息的主体是提高推荐系统效果的重要手段。Sensors Data 基于真实的商业案例,提供了成千上万条信息文章 及其关键词。参与者需要训练一个“关键词提取”的模型来提取10000条信息文章中的10条关键词。

  03数据

  备注:报名参赛或加入战队后,可获得资料下载权限。

  提供下载的数据集包括两部分:1.all_docs.txt,108295条信息文章数据,数据格式为:ID文章title文章text,除以\001在中间。2. train_docs_keywords.txt,1000个文章的关键词标注结果,数据格式为:ID关键词列表,中间除以\t。

  注意:注解数据中每个文章中的关键词不超过5个。关键词 已出现在 文章 的标题或正文中。需要注意的是“训练集文章的关键词组成的集合”和“测试集文章的关键词组成的集合”,这两个集合可能有交集,但收录和被收录之间不一定有关系。

  04 个人预赛第十一名方案

  基于NLP中的无监督学习方法提取关键词,这也是我第一次参加比赛。那时我是 NLP 的新手,所以对这次比赛印象深刻,在这里和大家分享一下。

  “SENSE杯”2018高校算法大师B榜排名(13/583)

  4.1 评分

  4.2 数据分析:

  4.3 起重技巧

  

  词性拼写错误

  这就是tf-idf提取关键字误差大的原因

  4.5 核心代码:

  # -*- coding: utf-8 -*-<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /># @Author  : quincyqiang<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /># @File    : analysis_for_06.py<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /># @Time    : 2018/9/5 14:17<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import pickle<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import pandas as pd<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />from tqdm import tqdm<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />from jieba.analyse import extract_tags,textrank # tf-idf<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />from jieba import posseg<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import random<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import jieba<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />jieba.analyse.set_stop_words('data/stop_words.txt') # 去除停用词<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />jieba.load_userdict('data/custom_dict.txt') # 设置词库<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />'''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />  nr 人名 nz 其他专名 ns 地名 nt 机构团体 n 名词 l 习用语 i 成语 a 形容词 <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />  nrt <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />  v 动词 t 时间词<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />'''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />test_data=pd.read_csv('data/test_docs.csv')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />train_data=pd.read_csv('data/new_train_docs.csv')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />allow_pos={'nr':1,'nz':2,'ns':3,'nt':4,'eng':5,'n':6,'l':7,'i':8,'a':9,'nrt':10,'v':11,'t':12}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /># allow_pos={'nr':1,'nz':2,'ns':3,'nt':4,'eng':5,'nrt':10}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />tf_pos = ['ns', 'n', 'vn', 'nr', 'nt', 'eng', 'nrt','v','a']<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />def generate_name(word_tags):<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    name_pos = ['ns', 'n', 'vn', 'nr', 'nt', 'eng', 'nrt']<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    for word_tag in word_tags:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        if word_tag[0] == '·' or word_tag=='!':<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            index = word_tags.index(word_tag)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            if (index+1) 1]<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        title_keywords = sorted(title_keywords, reverse=False, key=lambda x: (allow_pos[x[1]], -len(x[0])))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        if '·' in title :<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            if len(title_keywords) >= 2:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                key_1 = title_keywords[0][0]<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                key_2 = title_keywords[1][0]<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            else:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                # print(keywords,title,word_tags)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                key_1 = title_keywords[0][0]<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                key_2 = ''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            labels_1.append(key_1)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            labels_2.append(key_2)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        else:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            # 使用tf-idf<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            use_idf += 1<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            # ---------重要文本-----<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            primary_words = []<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            for keyword in title_keywords:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                if keyword[1] == 'n':<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                    primary_words.append(keyword[0])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                if keyword[1] in ['nr', 'nz', 'nt', 'ns']:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                    primary_words.extend([keyword[0]] * len(keyword[0]))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            abstract_text = "".join(doc.split(' ')[:15])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            for word, tag in jieba.posseg.cut(abstract_text):<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                if tag == 'n':<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                    primary_words.append(word)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                if tag in ['nr', 'nz', 'ns']:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                    primary_words.extend([word] * len(word))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            primary_text = "".join(primary_words)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            # 拼接成最后的文本<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            text = primary_text * 2 + title * 6 + " ".join(doc.split(' ')[:15] * 2) + doc<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            # ---------重要文本-----<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            temp_keywords = [keyword for keyword in extract_tags(text, topK=2)]<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            if len(temp_keywords)>=2:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                labels_1.append(temp_keywords[0])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                labels_2.append(temp_keywords[1])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            else:<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                labels_1.append(temp_keywords[0])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                labels_2.append(' ')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    data = {'id': ids,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            'label1': labels_1,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            'label2': labels_2}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    df_data = pd.DataFrame(data, columns=['id', 'label1', 'label2'])<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    df_data.to_csv('result/06_jieba_ensemble.csv', index=False)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    print("使用tf-idf提取的次数:",use_idf)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />if __name__ == '__main__':<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    # evaluate()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    extract_keyword_ensemble(test_data)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />© 2021 GitHub, Inc.<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />

  以下是来自国内大佬的无私潮流

  05“神策杯”2018高校算法大师赛二等奖

  代码链接:

  文章链接:

  团队:发SCI后才能毕业

  5.1 目录说明

  jieba:修改后的jieba库。

  词典:商店jieba词库。PS:词库来自搜狗百度输入法词库、爬虫获得的星条和LSTM命名实体识别结果。

  all_docs.txt:训练语料库

  train_docs_keywords.txt:我改了一些关键词明显错误的,比如D039180梁静茹-&gt;贾静雯,D011909太荣军-&gt;太荣军等。

  classes_doc2vec.npy:doc2vec+Kmeans在语料库上的聚类结果,默认参数为gensim。

  my_idf.txt:计算出的语料库的idf文件。

  lgb_sub_9524764012949717.npy 用于特征生成的 LGB 预测值

  stopword.txt:停用词

  get_Feature.ipynb:特征生成笔记本,生成训练集和测试集对应文件

  lgb_predict.py:预测和输出结果的脚本。需要 train_df_v7.csv 和 test_df_v7.csv。

  train_df_v7.csv、test_df_v7.csv:Get_Feature.ipynb的结果,notebook有详细的特征描述

  word2vec模型下载地址:提取码:tw0m。

  doc2vec模型下载地址:链接:提取码:0ciw。

  5.2 操作说明

  

  运行 Get_Feature.ipynb 获取 train_df_v7.csv 和 test_df_v7.csv。

  运行 lgb_predict.py 得到结果 sub.csv。

  numpy 1.14.0rc1<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />pandas 0.23.0<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />sklearn 0.19.0<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />lightgbm 2.0.5<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />scipy 1.0.0<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />

  5.3 解题思路描述

  使用jieba的tfidf方法筛选出Top20候选人关键词

  为每个样本的候选关键词提取对应的特征,将关键词的提取视为一个普通的二分类问题。特征可以分为以下两类:

  样本文档本身的特征:如文本长度、句子数量、聚类结果等;

  候选关键词自身特点:关键词长度、逆词频等;

  样本文本与候选关键词的交互特征:词频、头词频、tfidf、主题相似度等;

  候选关键词之间的特征:主要是关键词之间的相似特征。

  候选关键词与其他样本文档的交互特征:这里有两个非常强的特征,第一个是候选关键词在整个数据集中出现的频率,第二个类似于点击率,统计整个文档中预测为正样本的概率结果个数大于0.5(我提到这个特性的时候,大概率会过拟合,但是效果出乎意料的好,所以没有做对应平滑,可能是因为结果只选择了Top2的关键词,这里0.5的概率会有一定的平滑效果,具体操作请参考lgb_predict.py的31-42行)。

  使用LightGBM解决上述二分类问题,然后根据LightGBM的结果选择每个文本的预测概率Top2的词作为关键词的输出。

  06 第六名计划 Rank 6 / 622

  代码链接:

  07总结

  该任务属于短语挖掘或关键词挖掘。在接触NLP的过程中,很多同学都在研究如何从文本中挖掘关键词。经过近几年NLP技术的发展,大致总结了以下几种方法。在上面共享的三个方案中:

  基于无监督方法:LDA、TFIDF、TextRank

  基于特征工程:基于无监督生成候选词,然后构造特征来训练二分类模型

  基于深度学习的关键词提取:span、bio、bmes crf序列标注等方法

  08更多信息

  谈谈医疗保健中的短语挖掘

  加微信交流群:1185918903 备注:ChallengeHub01

  总结:企查查SEO亮点分析、采集+精准词库=高权重

  最近又有朋友让我分析一下七叉叉。本着知识共享的原则,结合自己浅薄的认知和知识,给大家讲讲七叉叉的SEO亮点,希望能帮助更多的兄弟了解SEO。自然!

  我之前也分析过顺奇网和58网。如果你喜欢它,你可以看看。58同城的词库比较笼统一点,七叉搜索比较准确。与以上两者相比,顺奇网的词更加复杂,不同的业务,不同的词库,不分级别。

  (内容,模板)稀缺

  现在很多人实现了SEO,仍然认为原创是SEO的核心。七叉叉就是对这种观点的最大否定。因为上面的信息基本都是采集。

  不过目测采集的内容应该是调用国家数据库吧,因为国内每个企业的信息应该不会那么好采集,就算是采集,也有仍然是不准确的情况,因为非权威网站上的企业信息的信任度比较低。只有国家信息才能准确。

  

  内容解决了,七叉叉在用户体验和模板方面都做得很好。在之前的课程中,我们也谈到了影响网站和收录排名的因素,模板也是其中之一。.

  *敏*感*词*的网站到最后,绝对是一场量级的较量。词库决定权重,收录 决定词库。收录 这么大的规模,绝对不是几十上百人能做到的。

  准确的词库定位

  词库的定位与业务直接相关,但就竞争而言,七叉戟的词库远小于58同城的词库。七叉叉的词库一般以【企业名称】【法人名称、股东名称】为主,而58则主要以本地服务为主,比如XXX搬家、XXXX租车,大家自然明白很难关键词 轻松。

  

  但是,词库的准确定位意味着客户将更加准确。当你的规模达到几千万、几亿的时候,长尾带来的流量是相当恐怖的,而这些恐怖流量的日访问量网站,增加的信任度绝不是普通小站点可比的.

  就像之前和58聊天一样,以品牌流量为源头,带动网站的整体信任度。信任度高后,长尾流量来了,回馈给网站,一次又一次,良性循环!

  学习和应用

  其实为什么要分析七叉叉呢?因为七叉叉的词库难度比较低。我们可以将他的词库导出为权重站!

  比如我之前做过人名站,可以做公司名站,或者其他站,毕竟有词库,而且内容是聚合的,即使是随机生成的,还是分分钟的分钟。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线