"""深度学习用于文本和序列
对于处理文本(单词或字符)序列、时间序列和一般的序列数据常用的两种算法:
①循环神经网络②一维卷积神经网络
其具体应用:
1.文档分类和时间序列分类,比如识别文章主题或书的作者
2.时间序列对比,比如评估两个文档或两支股票行情的相关程度
3.序列到序列的学习,比如机器翻译
4.情感分析,比如将推文或电影评论的情感划分为正面或负面
5.时间序列预测,比如根据某地最近的天气数据来预测未来天气"""
"""1.处理文本数据
由于神经网络只能处理张量数据,所以首先应该将文本数据进行向量化(verctorize)
常见方法:
①将文本分割为单词,并将每个单词转换为一个向量
②将文本分割为字符,并将每个字符转换为一个向量
③提取单词或字符的n-gram,并将每个n-gram转换为一个向量。n-gram是多个连续单词或字符的集合
文本分解而成的单元(单词、字符、n-gram)称之为标记(token),将文本分解成标记的过程称之为分词(tokenization)
如何将分词生成的标记于向量相关联?
①one-hot编码
②标记嵌入(词嵌入 word embedding)
"""
"""one-hot编码
将每个单词或字符与一个唯一的整数索引相关联,然后将这个整数索引i转换为长度为N的二进制向量(N是词表大小)
,这个向量只有第i个元素是1,其余元素为0"""
"""Embedding编码(词嵌入,word embedding)
one-hot编码得到的向量是二进制的,稀疏的(绝大部分元素都是0)、维度很高(维度大小等于词表中单词个数)
word embedding:低维的浮点数向量,并且词嵌入是从数据中学习得到的,词向量可以将更多的信息塞入更低的维度中
获取词嵌入的方法:
1.在完成主任务(比如文档分类,情感预测)的同时学习词嵌入,首先随机初始化词向量,然后对这些词向量进行学习,学习过程与神经网络权重学习一致
2.在不同于待解决的机器学习任务上预计算好词嵌入,然后将其加载到模型中,这些词嵌入叫做预训练词嵌入"""
from tensorflow.keras import layers
import numpy as np
"""
1.至少包含两个参数,标记的个数(词表中单词数)和嵌入的维度(每一个单词最后要表示的向量维度)
2.原理为:将其理解为一个字典,其会将整数索引(特定单词)映射为密集向量
3.其输入形状为[samples,sequences_length],且其输入的长度是可变的,即sequence_length可以为任意长度
4.其输出的形状为:[samples,sequences_length,embedding_dimensionality]"""
"""应用Embedding+Dense用于IMDB电影评论情感分类"""
"""使用预训练的词嵌入:
如果当前训练数据很少,无法从头开始学习适合任务的词嵌入,此时我们可以使用预训练的词嵌入
常用的词嵌入数据库:word2vec,Glove
本次实验展示如何使用Glove词嵌入,我们从imdb原始文本数据集开始进行处理"""
import os
train_dir="aclImdb_v1/aclImdb/train"
def text_preprocess(dir_path):
"""
:param dir_path: 数据集路径
:return: texts:文本列表,labels:文本标签
"""
texts=[]
labels=[]
for label_type in ["pos","neg"]:
dir_fname=os.path.join(dir_path,label_type)
for fname in os.listdir(dir_fname):
if fname[-4:]==".txt":
f=open(os.path.join(dir_fname,fname),encoding="utf-8")
texts.append(f.read())
f.close()
if label_type=="pos":
labels.append(1)
else:
labels.append(0)
return texts,labels
train_texts,train_labels=text_preprocess(train_dir)
print("train texts:",len(train_texts),"\ttrain labels:",len(train_labels))
"""对原始数据进行分词:
由于预训练的词嵌入对样本数据很少的任务特别有用,(如果数据量很多的话,从头学习词嵌入效果会更好
所以我们对IMDB数据集进行划分,取200个样本作为训练集,取10000个样本作为验证集,并将句子长度统一为100
"""
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
maxlen=100
training_samples=200
validate_samples=10000
max_words=10000
tokenizer=Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(train_texts)
sequences=tokenizer.texts_to_sequences(train_texts)
word_index=tokenizer.word_index
print(f"有{len(word_index)}个不同的单词")
data=pad_sequences(sequences,maxlen=maxlen)
labels=np.array(train_labels)
print("data shape:",data.shape)
print("label shape",labels.shape)
indices=np.arange(data.shape[0])
np.random.shuffle(indices)
data=data[indices]
labels=labels[indices]
x_train=data[:training_samples]
y_train=labels[:training_samples]
x_val=data[training_samples:training_samples+validate_samples]
y_val=labels[training_samples:training_samples+validate_samples]
"""
下载Glove词嵌入
Glove词嵌入介绍:
下载链接:https://nlp.stanford.edu/projects/glove
"""
glove_dir="glove.6B"
embedding_index={}
with open(os.path.join(glove_dir,"glove.6B.100d.txt"),encoding="utf-8") as f:
for line in f:
values=line.split()
word=values[0]
coefs=np.asarray(values[1:])
embedding_index[word]=coefs
print(f"词向量的个数为:{len(embedding_index)}")
"""构建词向量矩阵:
词向量矩阵现状为:[max_words,embedding_dimension]
max_words:单词个数
embedding_dimension:每个单词对应向量的维度"""
embedding_dim=100
embedding_matrix=np.zeros((max_words,embedding_dim))
for word,i in word_index.items():
if i<max_words:
embedding_vector=embedding_index.get(word)
if embedding_vector is not None:
embedding_matrix[i]=embedding_vector
"""构建模型"""
from tensorflow.keras import layers
from tensorflow.keras import models,losses,optimizers
model=models.Sequential()
model.add(layers.Embedding(max_words,embedding_dim,input_length=maxlen))
model.add(layers.Flatten())
model.add(layers.Dense(32,activation="relu"))
model.add(layers.Dense(1,activation="sigmoid"))
model.summary()
model.layers[0].set_weights([embedding_matrix])
model.layers[0].trainable=False
model.compile(optimizer=optimizers.RMSprop(1e-4),loss=losses.binary_crossentropy,metrics=["acc"])
history=model.fit(x_train,y_train,batch_size=32,epochs=10,validation_data=(x_val,y_val))
model.save_weights("pre_trained_glove_model.h5")
import matplotlib.pyplot as plt
"""损失函数绘制"""
history_dict=history.history
train_loss_values=history_dict["loss"]
val_loss_values=history_dict["val_loss"]
epochs=np.arange(1,len(train_loss_values)+1)
plt.figure(1)
plt.plot(epochs,train_loss_values,label="training loss")
plt.plot(epochs,val_loss_values,label="val loss")
plt.title("Training and Val Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
"""精度(准确率)绘制"""
train_acc=history_dict["acc"]
val_acc=history_dict["val_acc"]
plt.figure(2)
plt.plot(epochs,train_acc,label="Training Acc")
plt.plot(epochs,val_acc,label="Val Acc")
plt.title("Training and Val Acc")
plt.xlabel("Epoch")
plt.ylabel("Acc")
plt.legend()
plt.show()