GloVe词向量生成模型
import shutil
import gensim
def getFileLineNums(filename):
f = open(filename, 'r')
count = 0
for line in f:
count += 1
return count
def prepend_line(infile, outfile, line):
# To prepend lines using bash utilities in linux
with open(infile, 'r') as old:
with open(outfile, 'w') as new:
new.write(str(line) + "\n")
shutil.copyfileobj(old, new)
def load(filename):
#输入GloVe模型文件
glove_file = filename
dimensions = 50
num_lines = getFileLineNums(filename)
dims = int(dimensions[:-1])
print(num_lines)
gensim_file = 'glove_model.txt'
gensim_file_line = "{} {}".format(num_lines, dims)
prepend_line(glove_file, gensim_file, gensim_file_line)
model = gensim.models.keyedvectors.load_word2vec_format(gensim_file, binary = False)
model_name = gensim_file[6:-4]
model.save(model_name)
return model
if __name__ == '__main__':
myfile = 'vectors.txt'
model = load(myfile)
print(len(model.vocab))
word_list = [u'to',u'one']
for word in word_list:
print(word, '--')
for i in model.most_similar(word, topn=10):
print(i[0],i[1])
print('')
LSTM单元
-
Long-Short Term Memory RNN 长短时记忆模型循环神经网络,是RNN的一种特殊实现
-
Long-Short Term Memory
-
short term memory
相对于当前的任务,有时我们只需考虑最近的信息"the clouds are in the sky"
-
-
long term memory
相关信息和需要它的点之间的距离很远。
RNN在short-term上表现不错,但long-term就不理想了,所以有人提出了LSTM,它被广泛地运用,并在相当多的问题上表现很好
上图为含有四个交互层的LSTM重复模型
LSTM元素标注示意图
LSTM的关键是细胞状态
- 顶部直线
穿过图标上方的水平直线,直接在整个链上运行,只有一些小的线性相互作用,让信息在流动的同时保持不变性。
- 阀门
LSTM有能力向细胞状态中添加或移除信息,这种精细调整通过阀门的结构来实现。阀门可以让信息有选择地通过。它们由一个S形网络和一个逐点乘法操作组成。
S形网络层输出[0,1]的一个数,描述应该让每个组件通过多少信息。0就是什么也不让过,1就是每个信息都可以通过。
一个LSTM含有三个这样的阀门,来保护和控制细胞状态。
- 忘记阀门层: f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) {{f}_{t}}=\sigma ({{W}_{f}}\cdot [{{h}_{t-1}},{{x}_{t}}]+{{b}_{f}}) ft=σ(Wf⋅[ht−1,xt]+bf)
用于决定从细胞状态中扔掉哪些信息,这由一个叫做忘记阀门层的S形网络层实现。
- 输入阀门层:KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ & {{i}_{t}}=…
在丢掉一些信息之后,下一步要决定把哪些信息存储在细胞状态中。由以下两部分组成。
- 决定要更新的值
- 创造新的候选值向量
- 计算细胞状态: C t = f t ∗ C t − 1 + i t ∗ C ~ t {{C}_{t}}={{f}_{t}}*{{C}_{t-1}}+{{i}_{t}}*{{{\tilde{C}}}_{t}} Ct=ft∗Ct−1+it∗C~t
将旧的细胞状态 C t − 1 {{C}_{t-1}} Ct−1更新为 C t {{C}_{t}} Ct
- 输出阀门层:KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ & {{o}_{t}}=…
首先会运行一个S网络层,用于决定细胞状态的哪些部分会被输出,然后将细胞状态做tanh运算,得到[-1,1]的值。
LSTM的大体结构
相比于原始的RNN的隐藏层(hidden state),LSTM增加了一个细胞状态(cell state)
LSTM在t时刻的输入与输出:首先,输入有三个:细胞状态 C t − 1 {{C}_{t-1}} Ct−1,隐藏层状态 h t − 1 {{h}_{t-1}} ht−1,t时刻输入向量 X t {{X}_{t}} Xt,而输出有两个:细胞状态 C t {{C}_{t}} Ct,隐藏层状态 h t {{h}_{t}} ht。其中 h t {{h}_{t}} ht还作为t时刻的输出。
- 细胞状态 C t − 1 {{C}_{t-1}} Ct−1的信息一直在上面那条线上传递,t时刻的隐藏层状态 h t − 1 {{h}_{t-1}} ht−1,t时刻输入向量 X t {{X}_{t}} Xt会对 C t {{C}_{t}} Ct进行适当修改,然后传到下一时刻去。
- C t − 1 {{C}_{t-1}} Ct−1会参与t时刻输出 h t {{h}_{t}} ht的计算。
- 隐藏层状态 h t − 1 {{h}_{t-1}} ht−1的信息,通过LSTM的门结构,对细胞状态进行修改,并参与输出的计算。
LSTM也是RNN的一种,输入基本没什么差别。通常我们需要一个时序结构喂给LSTM,数据会被分为t个部分,也即 X t {{X}_{t}} Xt, X t {{X}_{t}} Xt可以看作是一个向量,在实际训练的时候,我们会用batch来训练,通常它的shape是**(batch_size, input_dim)**。
两个隐藏层的初始值: C 0 {{C}_{0}} C0与 h 0 {{h}_{0}} h0一般是用全0初始化。两个隐藏层同样是响亮的形式,在定义LSTM的时候会定义隐层大小,输出的维度与对应输入是一致的。
遗忘门
[ h t − 1 , x t ] [{{h}_{t-1}},{{x}_{t}}] [ht−1,xt]表示把两个向量连接起来, f t {{f}_{t}} ft为输出。$\sigma 表 示 s i g m o i d 函 数 , 它 的 输 出 是 在 0 到 1 之 间 的 , 这 个 输 出 表示sigmoid函数,它的输出是在0到1之间的,这个输出 表示sigmoid函数,它的输出是在0到1之间的,这个输出{{f}{t}} 逐 位 与 逐位与 逐位与{{C}{t-1}} 的 元 素 相 乘 , 当 的元素相乘,当 的元素相乘,当{{f}{t}} 的 某 一 位 值 为 0 的 时 候 , 的某一位值为0的时候, 的某一位值为0的时候,{{C}{t-1}}$对应的那一位信息就被干掉了,而值为(0,1)时,对应位的信息就保留了一部分,只有值为1的时候,对应信息才会完整保留。
更新门
这个门有两个部分
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ & {{i}_{t}}=\s…
一个是
C
~
t
{{{\tilde{C}}}_{t}}
C~t这里看作是新的输入带来的信息,tanh这个激活函数将内容归一化到[-1,1]。另一个是
i
t
{{i}_{t}}
it,此结构与遗忘门结构相同,可以看作新的信息保留哪些部分。
C t = f t ∗ C t − 1 + i t ∗ C ~ t {{C}_{t}}={{f}_{t}}*{{C}_{t-1}}+{{i}_{t}}*{{{\tilde{C}}}_{t}} Ct=ft∗Ct−1+it∗C~t表示对 C t {{C}_{t}} Ct进行更新,图左侧,遗忘门给出的 f t {{f}_{t}} ft这个值乘 C t − 1 {{C}_{t-1}} Ct−1,表示过去的信息有选择地遗忘(保留)。右侧同理,新的信息 C ~ t {{{\tilde{C}}}_{t}} C~t乘 i t {{i}_{t}} it表示新的信息有选择地遗忘,最后再把这两部分信息加起来,即新的状态 C t {{C}_{t}} Ct.
GRU单元
import shutil
shutil库作为os模块的补充,提供了复制、移动、删除、压缩等操作,对压缩包的处理是调用ZipFile和TarFile这两个模块来进行的。
shutil.copy(src,dst) #复制文件
shutil.copytree(src,dst) #复制文件夹
shutil.move(src,dst) #移动文件或文件夹
shutil.rmtree(src) #删除文件夹
zipobj.write() #创建一个压缩包
zipobj.namelist() #读取压缩包中的文件信息
zipobj.extract() #将压缩包中的单个文件解压出来
zipobj.extractall() #将压缩包中所有文件解压出来
import gensim
gensim是一款强大的自然语言处理工具,包括很多常见的模型
基本的语料处理工具
LSI
LDA
HDP
DTM
DIM
TF-IDF
word2vec
训练模型:
from gensim.models import word2vec
sentences = word2vec.Text8Corpus(u'分词后的爽肤水评论.txt')
model = word2vec.Word2Vec(sentences, size=50)
#model = word2vec.Word2Vec(sentences, mincount=5, size=50)
#首参是训练语料,二参是小于该数的单词会被剔除,默认为5,三参是神经网络的隐藏层单元数,默认100
y2 = model.similarity(u"好", u"还行")
print(y2)
for i in model.most_similar(u"滋润"):
print i[0],i[1]
模型导出
word2vec = gensim.models.word2vec.Word2Vec(sentences(), size=256, window=10, min_count=64,sg=1,hs=1,iter=10,workers=25)
word2vec.save('word2vec_wx')
模型导入
import numpy
model = gensim.models.Word2Vec.load('word2vec_wx')
pd.Series(model.most_similar(u'微信',topn=360000))
word_2x = numpy.load('word2vec_wx.wv.syn0.npy')
不能对已生成的模型进行再训练
.format
format作为python的格式字符串函数,主要通过字符串中的花括号{}来识别替换字段,从而完成字符串的格式化。
print("我叫{},今年{}岁。".format("小蜜",18))
#花括号个数决定了参数的个数,但花括号个数可以少于参数,当花括号多时,会报错。
通过数字参数传入位置参数,传入参数需注意以下事项:
- 数字须是大于0的整数
- 带数字的替换字段可以重复
- 数字形式的简单字段名相当于把字段当成一个序列形式。通过索引的形式进行一一取值
print("名字{0},家住{1}".format("橙留香","水果村"))
print("我爱{0}.\n他爱{1}。\n{0}爱{1}".format("红太狼","灰太狼"))
用关键字传递
print("我今年{age}岁,我在读{college}".format(age="18",college="大学"))
#关键字顺序可以随便放置
关键字和数字可以混合使用传递参数,但关键字参数须位于位置参数之后,混合使用的时候可以省略数字
可以使用元组和字典传参,两者可以混合使用,当混合使用的时候。位置参数要在关键字参数前面,元组要在字典前面
a=["鸣人","火影", "雏田"]
print("我是 {},我要当{}的男人".format(*a))
print("我是 {1},我要当{2}的男人".format(*a))
v={"name":"孙悟空","skill":"龟派气功"}
print("我是{name},我的绝招是{skill}".format(**v))
复合字段名的使用
-
format使用数字和变量名两种形式,这就是符合字段
-
复合字段名支持两种操作符
[] 方括号
. 点号
class Person:
def __init__(self,name,addr):
self.name = name
self.addr = addr
p = Person("孙悟空","包子山")
print("我是{0.name},家在{0.addr}".format(p))
#当只有一个字段时,就可以省略数字
print("我是{.name}".forname(q))
传递文件的属性
f = open("out.txt","w")
print("文件名为:"{.name}.format(f))
传递关键字
print("我是{p.name},家在{p.addr}".format(p=p))
print("我是{girl.name},家在{girl.addr}".format(girl=p))
rson(“孙悟空”,“包子山”)
print(“我是{0.name},家在{0.addr}”.format§)
#当只有一个字段时,就可以省略数字
print(“我是{.name}”.forname(q))
传递文件的属性
```python
f = open("out.txt","w")
print("文件名为:"{.name}.format(f))
传递关键字
print("我是{p.name},家在{p.addr}".format(p=p))
print("我是{girl.name},家在{girl.addr}".format(girl=p))