参考文献:Perform Sentiment Analysis with LSTMs Using TensorFlow
原来的代码可能哪里有点问题,准确率不应该有这么高的,修正后的准确率大概在60%,如图截图给出的是其中某次预测的准确率为51%的截图,可以看到准确率高的有70%,对于Twitter情感分析,学术顶尖的论文大概在70%的准确率。
![c48d1ca4bc84f4b8e96f002bdc6a188b.png](https://i-blog.csdnimg.cn/blog_migrate/14783a6d0b9a3490a0c09c66d6511a43.jpeg)
第一件事情是把单词变成向量。
通常使用 Word2Vec 的模型。该模型采用大量句子数据集(例如英文维基百科),并为语料库中的每个不同词输出向量。模型是通过将数据集中的每个句子进行训练,具有相似上下文的单词将在向量空间中放置在相近的位置。在自然语言中,当尝试确定其含义时,单词的上下文可能非常重要。
首先,要创建词向量。为简单起见,将使用预训练好的模型。
Glove 提供了预训练的数据,矩阵包含 40 万个词向量,每个维数为 50。
数据的格式是txt
,可以自己读入并处理,做好单词和向量的映射。
也可以找到 Glove 的二进制预训练数据,使用Tool to convert binary GloVe vectors to numpy array
工具将二进制的文件转换成npy
格式。
Glove 也提供了大量的训练样本和训练程序,网上也能找到大量的训练代码,只需要下载训练数据,然后运行官方提供的脚本,就可以完成训练。不过这一过程将耗费非常长的时间。
因为这一部分不是重点,所以我直接下载了npy
格式的预训练数据集。
你可以在这里下载: https://www. jxtxzzw.com/archives/41 02
先看看这一步是不是正确:
首先
import numpy as np
wordsList = np.load('wordsList.npy')
wordsList = wordsList.tolist()
wordsList = [word.decode('UTF-8') for word in wordsList]
wordVectors = np.load('wordVectors.npy')
导入数据集,然后使用wordList.index(word)
得到word
的索引号index
,并使用wordVector[index]
得到word
的词向量。
运行
print(wordsList.index("hello"))
print(wordVectors[wordsList.index("hello")])
输出hello
的索引号,并输出其词向量,得到索引号是 13075,词向量如下图:
![78c5d32178fd665ff291e8de12e0dce7.png](https://i-blog.csdnimg.cn/blog_migrate/dfa6a384c62d49181e20cbcacdff2a0e.jpeg)
对于句子的处理,可以用一个遍历来完成。
import numpy as np
wordsList = np.load('wordsList.npy')
wordsList = wordsList.tolist()
wordsList = [word.decode('UTF-8') for word in wordsList]
wordVectors = np.load('wordVectors.npy')
maxLength = 10
numDimensions = 300
s = "my name is hello world"
si = np.zeros(maxLength, dtype='int32')
s = s.strip().split()
for i in range(len(s)):
si[i] = wordsList.index(s[i])
print(si.shape)
print(si)
for i in range(len(s[i])):
print(wordVectors[si[i]])
之后要为整个训练集创建矩阵,但是每一个句子拥有多少个单词是不确定的,如何才能保证所有的记录拥有相同的维度(即,所有的句子拥有相同的长度,不足的补 0,超过的截断)却又不会丢失训练信息(即,大部分的句子仍然保留了所有的信息,而不至于被截断的部分太大)呢?
一种显而易见的做法是,令 90% 左右的句子都能够完整保留所有单词就行了。
在为整个训练集创建矩阵之前,首先花一些时间为拥有的数据类型做一下可视化,这会帮助我们确定设定最大序列长度的最佳值。
读入每个句子,然后用空格分隔,就可以统计出每个句子有多少个单词,将句子的长度添加进numWords
列表,然后用matplotlib
库将numWords
可视化。
with open("train.txt", "r", encoding='utf-8') as f:
while True:
line=f.readline()
if not line:
break
txt = line.split("t")[2]
counter = len(txt.split())
numWords.append(counter)
import matplotlib.pyplot as plt
plt.hist(numWords, 50)
plt.xlabel('Sequence Length')
plt.ylabel('Frequency')
plt.axis([0, 40, 0, 1000])
plt.show()
![e35c490afbbbcae1e75549f146fa0baa.png](https://i-blog.csdnimg.cn/blog_migrate/30fd13a437802fcbda2c659ce18565be.jpeg)
如图,可以看到,几乎所有的句子的长度都在 30 以下,那么,就可以直接令句子的最长值为 30。
这里没有取所有句子中真正最长的那个作为句子最长值,是因为这样会造成样本空间急剧增大,带来更大的运算量和更差的效率,而由于大部分都是 0,增加的运算量不能带来信息上的获益。
这样就定义了一个maxSeqLength
。
maxSeqLength = 30
下面尝试将某个句子转换成 id 矩阵。
例如我随便取了训练样本中的一句话,One of my best 8th graders Kory was excited after his touchdown...
,试着将这句话变成 id 矩阵,看看是什么效果。
首先用正则表达式去掉这句话中所有奇怪的数字、标点……并将所有字母换成小写。
record = "One of my best 8th graders Kory was excited after his touchdown"
tmp = np.zeros(maxSeqLength, dtype&