过了初赛就可以参加复赛,我初赛200+名(及格上榜的好像就400多人,具体名次我也不记得了),招行5.20给发了99.9的红包,很大方了~~~
赛题背景
财经新闻作为重要却海量的投资数据,无时无刻不在影响着投资者们的投资决策,为了更好地提示客户当下新闻事件对应的投资机会和投资风险,本课以研发“历史事件连连看”为目的,旨在根据当前新闻内容从历史事件中搜索出相似新闻报道,后期可以结合事件与行情,辅助客户采取相应投资策略。
该赛题是让参赛者为每一条测试集数据寻找其最相似的TOP 20条新闻,我们会根据参赛者提交的结果和实际的数据进行对比,采用mAP值作为评价指标。
具体实现
该题是一道文本相似度的题目,(我想也可以理解看成聚类啊,分类,具体如何操作我尚未试验)
讲一个小思路:
获取数据(读取中文文本)-->分词-->数据清洗(去掉停用词)-->计算tfidf--构建词袋模型转换为向量-->计算余弦相似度-->获取最相似的20条
额,这是一个baseline 的思路,比赛官方的结果还没有给出,我就先贴上自己baseline 的代码吧,其实还有很多要优化的地方,比如L:tfidf并不适合短文本,这样关键词提取上会出问题;另外VSM模型并不是计算相似性的最佳模型,个人见解,欢迎讨论.
科普一下:
常见的距离度量方法:
(1)欧式距离(2)Pearson相关性(3)cos余弦距离
注意注意!在推荐系统最常用的其实是第二种。
下面是我的一个计算文本相似性的简单代码啦:
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 27 21:49:31 2018
@author: susuxuer
"""
import jieba
import jieba.posseg as pseg
from gensim import corpora,models,similarities
import pandas as pd
import re
import time
# 加载数据集
'''
加载训练集方式:
loadDataSet('train_data.csv', 'UTF-8')
加载测试集方式:
loadDataSet('test_data.csv', 'gbk')
'''
def loadDataSet(filename,encode):
dataSet = pd.read_csv(filename, encoding = encode)
m,n = dataSet.shape
data = dataSet.values[:,-1]
dataId = dataSet.values[:,0]
return data.reshape((m,1)), dataId.reshape((m,1))
# numpy 数组转化为 list
def ndarrayToList(dataArr):
dataList = []
m,n = dataArr.shape
for i in range(m):
for j in range(n):
dataList.append(dataArr[i,j])
return dataList
# 创建停用词list
def stopwordslist(filePath):
stopwords = [line.strip() for line in open(filePath, 'r', encoding='UTF-8').readlines()]
return stopwords
# 去掉字符串特殊符号
def removeStr(listData):
strData = "".join(listData)
r1 = u'[0-9’!"#$%&\'()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+'
removeStrData = re.sub(r1, "",strData)
return removeStrData
# 对数据集分词
def wordSplit(data):
stopword = stopwordslist('ChineseStopWords.txt')
word = ndarrayToList(data)
m = len(word)
wordList = [] # 保存分词结果
for i in range(m):
rowListRemoveStr = removeStr(word[i])
rowList = [eachWord for eachWord in jieba.cut(rowListRemoveStr)] # 对每一行分词
wordRmoveList = []
for oneword in rowList:
if oneword not in stopword and word != '\t' and word != ' ':
wordRmoveList.append(oneword)
wordList.append(wordRmoveList)
return wordList
if __name__ == "__main__":
start = time.clock()
with open("result.txt","a") as fr:
fr.write('source_id')
fr.write('\t')
fr.write('target_id')
fr.close
# 加载训练集与测试集
trainData,trainDataId = loadDataSet('train_data.csv', 'UTF-8')
testData,testDataId = loadDataSet('test_data.csv', 'gbk')
print('训练集、测试集加载完成')
# 对训练集与测试集分词
trainDataSplit = wordSplit(trainData)
print('训练集分词完成')
testDataSplit = wordSplit(testData)
print('测试集分词完成')
# 制作语料库
dictionary = corpora.Dictionary(trainDataSplit) # 获取词袋
corpus = [dictionary.doc2bow(doc) for doc in trainDataSplit] # 制作语料库
print('语料库制作完成')
# 使用 TF-IDF 模型对语料库建模
tfidf = models.TfidfModel(corpus)
m = len(testDataSplit)
for i in range(m):
print('测试第%d条数据' %i)
testVec = dictionary.doc2bow(testDataSplit[i])
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
sim = index[tfidf[testVec]]
simNumList = sorted(enumerate(sim), key=lambda item: -item[1])
with open("result.txt","a") as fr:
for j in range(21):
if str(int(testDataId[i])) == str(int(simNumList[j][0]+1)):
continue
fr.write('\n')
fr.write(str(int(testDataId[i])))
fr.write('\t')
fr.write(str(int(simNumList[j][0]+1)))
elapsed = (time.clock() - start)
print('Time use', elapsed)
还望大神们勿喷,这是第一版本,后面版本尚不能公开,此版本Python 3.6可以运行,python2.7可能会出现编码错误。
我之前用的python 2.7 ,Unicode ,GBK,UTF-8,ASCII把我搞得很懵逼,总是出错,给大家科普一下编码:
ASCII:最开始只在美国使用,是一个字节,前128个为标准ASCII码,后128个称为扩展ASCII码。许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII 码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。
Unicode 是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案,又称统一码。
GBK编码:是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符。
UTF-8:是万国码,UTF8编码格式很强大,支持所有国家的语言,正是因为它的强大,才会导致它占用的空间大小要比GBK大,对于网站打开速度而言,也是有一定影响的。