赞
踩
文本是常用的序列数据之一
可理解为字符序列或单词序列
映射书面语言的统计结构
文本向量化:将文本转换成数值张量的过程
实现方法
将文本分解成单元叫做标记(token)
将文本分解成标记的过程叫做分词(tokenization)
所有文本向量化过程都是应用某种分词方案,然后将数值向量与生成标记相关联
n-gram
1.单词级的one-hot编码示例
#单词级的one-hot编码 import numpy as np samples=['the cat sat on the mat','The dog ate my homework'] token_index={} for sample in samples: for word in sample.split(): if word not in token_index: token_index[word]=len(token_index)+1 #为每个唯一单词指定唯一索引 max_length=10 #只考虑样本的前max_length个单词 results=np.zeros(shape=(len(samples), max_length, max(token_index.values())+1))
#字符级的one-hot编码
import string
samples=['the cat sat on the mat','The dog ate my homework']
characters=string.printable #所有可打印的ASCII字符
token_index=dict(zip(range(1,len(characters)+1),characters))
max_length=50
results=np.zeros((len(samples),max_length,max(token_index.keys())+1))
for i,sample in enumerate(samples):
for j,character in enumerate(sample):
index=token_index.get(character)
results[i,j,index]=1
#print(j,character)
#用keras实现单词级的one-hot编码
from keras.preprocessing.text import Tokenizer
samples=['the cat sat on the mat','The dog ate my homework']
#创建一个分词器,设置只考虑前1000个单词
tokenizer=Tokenizer(num_words=1000)
#构建单词索引
tokenizer.fit_on_texts(samples)
#将字符串转换为整数索引组成的列表
sequences=tokenizer.texts_to_sequences(samples)
#也可以直接得到one-hot二进制表示
one_hot_results=tokenizer.texts_to_matrix(samples,mode='binary')
#找回单词索引
word_index=tokenizer.word_index
使用词嵌入
单词与向量关联的另一种方法,使用密集的词向量(word vector)也叫词嵌入(word embedding)
onehot编码得到的是二进制的,稀疏的,维度很高
词嵌入是从数据中学习得到的
获取词嵌入的方法:
#将一个embedding层实例化
from keras.layers import Embedding
#Embedding至少需要需要两个参数,标记的个数(1000)和嵌入的维度(64
)
embedding_layer=Embedding(1000,64)
Embedding层可以理解为一个字典,将整数索引映射为密集向量,
实际上是一种字典查找:单词索引->Embedding层->对应的词向量
2. 使用与训练的词嵌入
自然语言处理中使用预训练词嵌入,原理与图像分类中使用预训练的卷积神经网络一样
#下载IMDB原始数据的标签 import os imdb_dir='****' train_dir='***' labels=[] texts=[] for label_type in['neg','pos']: dir_name=os.path.join(train_dir,label_type) for fname in os.listdir(dir_name): if fname[-4:]=='.txt': f=open(os.path.join(dir_name,fname)) texts.append(f.read()) f.close() if label_type=='neg': labes.append(0) else: label.append(1)
#对IMDB原始数据文本进行分词 #对IMDB原始数据文本进行分词 from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences import numpy as np maxlen=100 #阶段100个单词后的评论 training_samples=200 #在200个样本上训练 validation_samples=10000 #在10000个样本上验证 max_words=10000 #只考虑数据集中前一万个常见单词 tokenizer=Tokenizer(num_words=max_words) tokenizer.fit_on_texts(texts) sequences=tokenizer.texts_to_sequences(texts) word_index=tokenizer.word_index print("found %s unique tokens."%len(word_index)) data=pad_sequeces(sequences,maxlen=maxlen) labels=np.asarray(labels) print("shape of data tensor:",data.shape) print("shape of label tensor.",labels.shape) #将数据划分为训练集和测试集,但首先要打乱数据,因为一开始是排好序的 indices=np.arange(data.shape[0]) np.random.shuffle(indices) data=data[indices] label=labels[indices] x_train=data[:training_samples] y_train=labels[:training_samples] x_val=data[training_samples:training_samples+validation_samples] y_val=labels[training_samples:training_samples+validation_samples]
下载词嵌入
下载维基百科词嵌入,包含40万个单词的100维向量,
#对嵌入进行预处理
解析解压后的文件,构建一个单词映射维其向量表示的索引
glove_dir='downloads/glove/.6B'
embedding_index={}
f=open(os.path.join(glove_dir,'glove.6B.100d.txt'))
for line in f:
values=line.split()
word=values[0]
coefs=np.asarray(values[1:],dtype='float32')
embeddings_index[word]=coefs
f.close()
print('Found %s word vectors.'%len(embedding_index))
构建一个可以加载到embedding层中的嵌入矩阵,形状为(max_words,embedding_dim)的矩阵
对于单词索引为i的单词,矩阵元素i就是单词对应的embedding_dim维向量
索引0不代表任何单词或标记,只是一个占位符
#准备词嵌入矩阵
embedding=100
embedding_matrix=np.zeros((max_words,embedding_dim))
for word,i in word_index.get(word):
if i<max_words:
embedding_vector=embedding_index.get(word)
if embedding_vector is not None:
#嵌入索引中找不到的词,其嵌入矩阵全为0
embedding_matrix[i]=embedding_vector
#定义模型
from keras,models import Sequensial
from keras.layers import Embedding,Flatten,Dense
model=Sequensial()
model.add(Embedding(max_words,embedding_dim,input_length=maxlen))
model.add(Flatten())
model.add(Dense(32,activation='relu'))
model.add(Dense(1,activation='sigmoid'))
model.summary()
在模型中加载Glove嵌入
Embedding层只有一个权重矩阵(二维浮点数),其中每个元素i是与索引i相关联的词向量
model.layers[0].set_weights([embedding_matrix])
#冻结embedding层
#如果一个模型的一部分是经过预训练的(embedding),而另一部分是经过随机初始化的(分类器),那么在训练期间不应该更新预训练的部分,以避免丢失他们所保留的信息
#随机初始化层会引起较大梯度更新,破坏已学到的特征
model.layers[0].trainable=False
预训练模型与评估
model.compile(optimizer='rmsprop',
loss='binary_crossentropy'
metrics=['acc'])
history=model.fit(x_train,y_train,
epochs=10,
batch_size=32,
validation_data=(x_val,y_val)
)
model.save_weights('pre_trained_glove_model.h5')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。