磐创AI分享
作者 | Victor Sim
编译 | VK
来源 | Towards Data Science
情感分析是一个必不可少的工具,用于许多不同的任务。这包括从基于tweets预测股市情绪,到预测客户自动生成响应。Google的Word2Vec运行良好,但有一个很大的问题。
它需要大量的数据集。当谷歌训练Word2Vec网络时,它使用了数千个它有特殊访问权限的文档。如果要找到、规范化并使用足够的质量数据来让程序正常工作,那将是一场噩梦,使我无法在自己的项目中实现这一点
经过一段时间的思考,提出了一种将单词转换成向量的技术,是使用了与Google使用的Word2Vec方法完全不同的概念。
概念
让我们回到我们的最终目标:将一个单词转换成向量。向量作为程序的直接输出是困难的,这是由于在系统中训练两个同等权重的变量(就像向量的情况一样)。所以我们的最终输出是一个单数值。此值仍将转换为向量,第一个值为-1或1(表示积极或消极情绪),第二个值为任意值(表示情绪的大小)。
如果我们为每个单词生成一个值,我们可以使用梯度下降来改变这个值,以便每次计算出情绪。
如何执行反向传播?简单,对tweet中每个单词的所有值Sigmoid,输出0到1之间的值,0为负,1为正。
代码
步骤1 |先决条件:
代码语言:javascript复制import os
from pandas import read_csv
import string
import numpy as np
这些库是程序工作所必需的。
步骤2 |访问数据集:
代码语言:javascript复制os.chdir(r'XXXXXX')
csv = read_csv('stock_data.csv')
csv
将XXXXX更改为存储数据集的目录。你可以从这个链接得到股票情绪数据集:https://www.kaggle.com/yash612/stockmarket-sentiment-dataset
步骤3 |准备数据集步骤
代码语言:javascript复制X = csv['Text'].values
y = csv['Sentiment'].values
np.unique(y)
X[5]
提取数据集的X和y值很简单,因为它在数据集中的形式类似。
步骤4 |清理数据集
代码语言:javascript复制counter = 0
for i in range(len(y)):
if y[i] != 1:
counter = 1
y[i] = 0
new_X = []
for i in range(len(X)):
try:
words = X[i].split()
counter = 0
while True:
upper = False
for word in words:
if word.isupper() or 'https' in word or word[0] == '#' or not(word.isalpha()):
words.remove(word)
upper = True
if upper == False:
break
counter = 1
for i in range(len(words)):
words[i] = words[i].lower()
new_X.append(words)
except:
pass
X = new_X
flatten = lambda t: [item for sublist in t for item in sublist]
all_words = flatten(X)
unique = list(np.unique(all_words))
unique.sort()
vectors = np.random.randn(len(unique),1)
我已经从数据集中删除了链接、标签和公司名称,以防止模型只会从公司目前的表现中获取情绪。
我还需要生成一个唯一单词的列表,这样向量就可以按索引分配了。
步骤5 |向量化、传播和训练:
代码语言:javascript复制def sigmoid(x):
return 1/(1 np.exp(-x))
def sigmoid_p(x):
return sigmoid(x)*(1 -sigmoid(x))
def predict_sentiment(tweet):
sentiment = 1
for word in tweet:
index = unique.index(word)
sentiment *= vectors[index]
sentiment = sigmoid(sentiment)
return sentiment
def adjust_vectors(pred_sentiment,true_sentiment,tweet):
dloss_dpred = 2*(true_sentiment-pred_sentiment)
dloss_dvec = []
vectors_iq = []
vectors_index = []
for word in tweet:
index = unique.index(word)
vectors_iq.append(vectors[index])
vectors_index.append(index)
product = np.prod(vectors_iq)
for i in range(len(vectors_iq)):
dloss_dvec.append(sigmoid_p(product)/vectors_iq[i])
for i in range(len(vectors_index)):
vectors[i] -= dloss_dvec[i] * 0.1
return vectors
for epoch in range(100):
print('EPOCH',str(epoch 1))
for i in range(len(X)):
pred_sentiment = predict_sentiment(new_X[i])
vectors = adjust_vectors(pred_sentiment,y[i],new_X[i])
基本上,根据tweet中的其他词计算梯度,可以正确地改变向量,从而在预测推特情绪时获得更高的准确率。
步骤6 |观察向量
代码语言:javascript复制import random
from matplotlib import pyplot as plt
num = 5
for i in range(num):
random_num = random.randint(0,len(vectors)-1)
vec = vectors[random_num]
if vec < 0:
vec_y = -1
else:
vec_y = 1
vec_X = vec/vec_y
word = unique[random_num]
plt.plot(vec_X,vec_y,'o')
plt.annotate(word,(vec_X,vec_y))
这个程序可以让我们看到传染病的严重程度和情绪,观察程序的结果可以得到不同结论。在对数据集进行清理和规范化处理之后,可以对结果进行改进,并观察结果并发现明显的错误。
结论
如果你仍然不相信使用向量来计算单词,请考虑向量的这个属性:向量有一个大小,可以使用毕达哥拉斯定理计算出来。在我们所看到的所有向量中,它们都是相对于原点的。
如果我们认为X轴代表情绪的严重程度,而y轴代表积极/消极,我们就知道原点是完全中性的。通过计算向量的大小,它可以计算出意见偏离原点的程度,或者意见有多极端。
以下是计算此值的函数:
代码语言:javascript复制def calculate_magnitude(vec):
if vec < 0:
vec_y = -1
else:
vec_y = 1
vec_X = vec/vec_y
sum_value = vec_X**2 vec_y**2
return np.sqrt(sum_value)
calculate_magnitude(vectors[100])
感谢你阅读我的文章!