本文主要讲述了通过FastText的分类方法,根据每日新闻来预测金融市场。
数据集:Combined_News_DJIA.csv
读入数据集:
数据集主要分为三个部分:Date(日期),Label(0:股票下跌;1:股票上涨),Top0-25(新闻内容)
一、拆分出训练集和测试集
由于只有这一个数据集,需要对上面这个数据集拆分出训练集和测试集。代码如下:
将2015-01-01(不包含)之前的数据作为训练集,将2015-01-01(包含)之后的数据作为测试集
二、对数据集预处理
1.将每日新闻存放在数组内
在拆分好数据集后,需要对这些数据集预处理成方便训练模型的数据集,代码如下:
其中每条语句都有注释方便理解。上述代码主要获得五个东西:
X_train:一维数组,[a,b,c...,d,e,f],a表示训练集中第一天中所有25条新闻合并一起,用空格隔开。
X_test:一维数组,[a,b,c...,d,e,f],a表示测试集中第一天中所有25条新闻合并一起,用空格隔开。
y_train:一维数组,[0,1,0...,1,0,0],由0,1组成,对应训练集中每一条股票的涨跌。
y_test:一维数组,[0,1,0...,1,0,0],由0,1组成,对应测试集中每一条股票的涨跌。
corpus:一维数组,存储所有的新闻,每一项表示一条新闻(不是X_train中的25条合一起了)。
2.将每日新闻拆分为单词
得到上述五个变量后,因为存储的每一条新闻都是一句或几句话,计算机处理起来不方便,需要把每一句话拆分成单词才好处理,代码如下:
导入了一个word_tokenize函数,其功能为将一句话拆分成单词然后存储在一个列表当中,执行这几条语句后,本来为存储每一句话的一维数组将变为存储单词的二维数组。
3.去除停止词
拆分好每一个单词后,需要去除停止词,停止词就是对全文分析毫无意义的词汇,比如一些语气助词之类的,可参考这篇文章:
https://blog.csdn.net/Da_wan/article/details/104640649
去除停止词函数代码:
# 停止词
from nltk.corpus import stopwords
stop = stopwords.words('english')
# 数字
import re
def hasNumbers(inputString):
return bool(re.search(r'\d', inputString))
# 特殊符号
def isSymbol(inputString):
return bool(re.match(r'[^\w]', inputString))
# lemma
from nltk.stem import WordNetLemmatizer
wordnet_lemmatizer = WordNetLemmatizer()
def check(word):
"""
如果需要这个单词,则True
如果应该去除,则False
"""
word= word.lower()
if word in stop:
return False
elif hasNumbers(word) or isSymbol(word):
return False
else:
return True
# 把上面的方法综合起来
def preprocessing(sen):
res = []
for word in sen:
if check(word):
# 这一段的用处仅仅是去除python里面byte存str时候留下的标识。。之前数据没处理好,其他case里不会有这个情况
word = word.lower().replace("b'", '').replace('b"', '').replace('"', '').replace("'", '')
res.append(wordnet_lemmatizer.lemmatize(word))
return res
preprocessing()为上述粘贴代码的函数,功能就是去除停止词,以及一些特殊符号。
执行完上述操作后,便得到干净所需的单词数据,可以用这些数据去训练数据集了。
4.重新组接成新句子
在去除完生成词后,我们需要重新拼接为新的句子,这些句子都是没有语法的,因为上述操作已经将部分单词去除,看起来会非常违和,但是计算机看这些句子就不用在意,因为之前的这些预处理操作只是让数据显得更加干净,准确率更高。先上代码:
这部分代码当中在每一天的新闻信息后面多加了一个__label__1或者__label__0这样一个标签,是因为fasttext约定俗成的东西,方便其训练模型,0,1表示股票涨跌。加好标签后,然后每个单词用空格分隔开存储,这时每一天都有25条新闻合并成一个句子后面还加了一个label,这就是我们最终要训练的数据。
而测试集是用来测试label是0,还是1的所以不用加label直接拼接成句子就行。
5.将数据集保存为文本
代码十分简单,有三个txt文件,一个是训练集的文本,一个是测试集的文本,最后一个是检验测试集准确率的文本
三、调用Fastext模块,训练模型
import fasttext
clf = fasttext.train_supervised('./input/train_ft.txt', dim=256, ws=5, neg=5, epoch=100, min_count=10, lr=0.1, lr_update_rate=1000, bucket=200000)
将训练集的txt文件导入到模型中训练。最后通过简单的clf.predict(X_test)就可以简单的得出测试集中的label是0还是1,
import re
y_temp = []
y_preds =[]
# 我们用predict来给出判断
labels = clf.predict(X_test)
for x in np.array(labels[0]).flatten():
y_temp = np.array(re.findall('\d+',x)).astype("int")
y_preds.append(y_temp)
y_preds = np.array(y_preds).flatten()
# 我们来看看
print(len(y_test))
print(y_test)
print(len(y_preds))
print(y_preds)
from sklearn import metrics
# 算个AUC准确率
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_preds, pos_label=1)
print(metrics.auc(fpr, tpr))
有一段与我课程上的不一样,因为预测的结果是__label__0,不是单纯的数字,所以用re来匹配出其中的数字来存储,最后得到的y_preds就是我们预测的结果,每一项就表示当天股票是涨还是跌了。
四、总结
本文通过Fasttext预测结果并不是很好(只有40%的准确率),只是单纯的记录一下fasttext这样一种方法。
在小量数据上,fasttext是跑不出很理想的结论的,还不如我们自己带上一个SVM的效果。但是面对大量数据和大量label,它的效果就体现出来了。
本文需要的数据集,以及源代码也已经上传(已经设置为0积分下载)。