AI:深度学习用于文本处理
同本文一起发布的另外一篇文章中,提到了 BlueDot 公司,这个公司致力于利用人工智能保护全球人民免受传染病的侵害,在本次疫情还没有引起强烈关注时,就提前一周发出预警,一周的时间,多么宝贵!
他们的 AI 预警系统,就用到了深度学习对文本的处理,这个系统抓取网络上大量的新闻、公开声明等获取到的数十万的信息,对自然语言进行处理,我们今天就聊聊深度学习如何对文本的简单处理。
文本,String 或 Text,就是字符的序列或单词的序列,最常见的是单词的处理(我们暂时不考虑中文,中文的理解和处理与英文相比要复杂得多)。计算机就是固化的数学,对文本的处理,在本质上来说就是固化的统计学,这样采用统计学处理后的模型就可以解决许多简单的问题了。下面我们开始吧。
处理文本数据
与之前一致,如果原始要训练的数据不是向量,我们要进行向量化,文本的向量化,有几种方式:
- 按照单词分割
- 按照字符分割
- 提取单词的 n-gram
我喜欢吃火……,你猜我接下来会说的是什么?1-gram 接下来说什么都可以,这个词与前文没关系;2-gram 接下来可能说“把,柴,焰”等,组成词语“火把、火柴、火焰”;3-gram 接下来可能说“锅”,组成“吃火锅”,这个概率更大一些。先简单这么理解,n-gram 就是与前 n-1 个词有关。
我们今天先来填之前挖下来的一个坑,当时说以后将介绍 one-hot,现在是时候了。
one-hot 编码
def one_hot():
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
# {'The': 1, 'cat': 2, 'sat': 3, 'on': 4, 'the': 5, 'mat.': 6, 'dog': 7, 'ate': 8, 'my': 9, 'homework.': 10}
print(token_index)
max_length = 8
results = np.zeros(shape=(len(samples), max_length, max(token_index.values()) + 1))
for i, sample in enumerate(samples):
for j, word in list(enumerate(sample.split()))[:max_length]:
index = token_index.get(word)
results[i, j, index] = 1.
print(results)
我们看到,这个数据是不好的,mat 和 homework 后面都分别跟了一个英文的句话 '.',要炫技写那种高级的正则表达式去匹配这个莫名其妙的符号吗?当然不是了,没错,Keras 有内置的方法。
def keras_one_hot():
samples = ['The cat sat on the mat.', 'The dog ate my homework.']
tokenizer = Tokenizer(num_words=1000)
tokenizer.fit_on_texts(samples)
sequences = tokenizer.texts_to_sequences(samples)
print(sequences)
one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')
print(one_hot_results)
word_index = tokenizer.word_index
print(word_index)
print('Found %s unique tokens.' % len(word_index))
这里的 num_words 和上面的 max_length 都是用来表示多少个最常用的单词,控制好这个,可以大大的减少运算量训练时间,甚至有点时候能更好的提高准确率,希望引起一定注意。我们还可以看到得到的编码的向量,很大一部分都是 0,不够紧凑,这会导致大量的内存占用,不好不好,有什么什么其他办法呢?答案是肯定的。
词嵌入
也叫词向量。词嵌入通常是密集的,维度低的(256、512、1024)。那到底什么叫词嵌入呢?
本文我们的主题是处理文本信息,文本信息就是有语义的,对于没有语义的文本我们什么也干不了,但是我们之前的处理方法,其实就是概率上的统计,,是一种单纯的计算,没有理解的含义(或者说很少),但是考虑到真实情况,“非常好” 和 “非常棒” 的含义是相近的,它们与 “非常差” 的含义是相反的,因此我们希望转换成向量的时候,前两个向量距离小,与后一个向量距离大。因此看下面一张图,是不是就很容易理解了呢:
可能直接让你去实现这个功能有点难,幸好 Keras 简化了这个问题,Embedding 是内置的网络层,可以完成这个映射关系。现在理解这个概念后,我们再来看看 IMDB 问题(电影评论情感预测),代码就简单了,差不都可以达到 75%的准确率:
def imdb_run():
max_features = 10000
maxlen = 20
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
model = Sequential()
model.add(Embedding(10000, 8, input_length=maxlen))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary()
history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)
我们的数据量有点少,怎么办呢?上一节我们在处理图像的时候,用到的方法是使用预训练的网络,这里我们采用类似的方法,采用预训练的词嵌入。最流行的两种词嵌入是 GloVe 和 Word2Vec,我们后面还是会在合适的时候分别介绍这两个词嵌入。今天我们采用 GloVe 的方法,具体做法我写在了代码的注释中。我们还是先看结果,代码还是放在最后:
很快就过拟合了,你可能觉得这个验证精度接近 60%,考虑到训练样本只有 200 个,这个结果真的还挺不错的,当然,你可能不信,那么我再给出两组对比图,一组是没有词嵌入的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uem4R2hO-1583414769394)(https://upload-images.jianshu.io/upload_images/2023569-23b0d32d9d3db11d?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]
验证精度明显偏低,再给出 2000 个训练集的数据:
这个精度就高了很多,追求这个高低不是我们的目的,我们的目的是说明词嵌入是有效的,我们达到了这个目的,好了,接下来我们看看代码吧:
#!/usr/bin/env python3
import os
import time
import matplotlib.pyplot as plt
import numpy as np
from keras.layers import Embedding, Flatten, Dense
from keras.models import Sequential
from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
def deal():
# http://mng.bz/0tIo
imdb_dir = '/Users/renyuzhuo/Documents/PycharmProjects/Data/aclImdb'
train_dir = os.path.join(imdb_dir, 'train')
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':
labels.append(0)
else:
labels.append(1)
# 对所有数据进行分词
# 每个评论最多 100 个单词
maxlen = 100
# 训练样本数量
training_samples = 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_sequences(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]
labels = 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]
# 下载词嵌入数据,下载地址:https: // nlp.stanford.edu / projects / glove
glove_dir = '/Users/renyuzhuo/Documents/PycharmProjects/Data/glove.6B'
embeddings_index = {}
f = open(os.path.join(glove_dir, 'glove.6B.100d.txt'))
# 构建单词与其x向量表示的索引
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(embeddings_index))
# 构建嵌入矩阵
embedding_dim = 100
embedding_matrix = np.zeros((max_words, embedding_dim))
for word, i in word_index.items():
if i < max_words:
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
embedding_matrix[i] = embedding_vector
# 构建模型
model = Sequential()
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 层,且将其设置为不可训练
model.layers[0].set_weights([embedding_matrix])
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')
# 画图
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.show()
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
if __name__ == "__main__":
time_start = time.time()
deal()
time_end = time.time()
print('Time Used: ', time_end - time_start)
本文首发自公众号:RAIS
AI:深度学习用于文本处理的更多相关文章
- 2.keras实现-->深度学习用于文本和序列
1.将文本数据预处理为有用的数据表示 将文本分割成单词(token),并将每一个单词转换为一个向量 将文本分割成单字符(token),并将每一个字符转换为一个向量 提取单词或字符的n-gram(tok ...
- 【AI in 美团】深度学习在文本领域的应用
背景 近几年以深度学习技术为核心的人工智能得到广泛的关注,无论是学术界还是工业界,它们都把深度学习作为研究应用的焦点.而深度学习技术突飞猛进的发展离不开海量数据的积累.计算能力的提升和算法模型的改进. ...
- 万字总结Keras深度学习中文文本分类
摘要:文章将详细讲解Keras实现经典的深度学习文本分类算法,包括LSTM.BiLSTM.BiLSTM+Attention和CNN.TextCNN. 本文分享自华为云社区<Keras深度学习中文 ...
- 将迁移学习用于文本分类 《 Universal Language Model Fine-tuning for Text Classification》
将迁移学习用于文本分类 < Universal Language Model Fine-tuning for Text Classification> 2018-07-27 20:07:4 ...
- 一文看懂AI深度学习丨曼孚科技
深度学习(Deep Learning)是机器学习的一种,而机器学习是实现人工智能的必经途径. 目前大部分表现优异的AI应用都使用了深度学习技术,引领了第三次人工智能的浪潮. 一. 深度学习的概念 深度 ...
- AI - 深度学习之美十四章-概念摘要(8~14)
原文链接:https://yq.aliyun.com/topic/111 本文是对原文内容中部分概念的摘取记录,可能有轻微改动,但不影响原文表达. 08 - BP算法双向传,链式求导最缠绵 反向传播( ...
- AI - 深度学习之美十四章-概念摘要(1~7)
原文链接:https://yq.aliyun.com/topic/111 本文是对原文内容中部分概念的摘取记录,可能有轻微改动,但不影响原文表达. 01 - 一入侯门"深"似海,深 ...
- 深度学习之文本分类模型-前馈神经网络(Feed-Forward Neural Networks)
目录 DAN(Deep Average Network) Fasttext fasttext文本分类 fasttext的n-gram模型 Doc2vec DAN(Deep Average Networ ...
- 最佳实践:深度学习用于自然语言处理(Deep Learning for NLP Best Practices) - 阅读笔记
https://www.wxnmh.com/thread-1528249.htm https://www.wxnmh.com/thread-1528251.htm https://www.wxnmh. ...
随机推荐
- 量化投资_轻松实现MATLAB蒙特卡洛方法建模
1 目录 * MATLAB随机数的产生 - Uniform,Normal & Custom distributions * 蒙特卡洛仿真 * 产生股票价格路径 * 期权定价 - 经典公式 - ...
- springboot集成websocket实现大文件分块上传
遇到一个上传文件的问题,老大说使用http太慢了,因为http包含大量的请求头,刚好项目本身又集成了websocket,想着就用websocket来做文件上传. 相关技术 springboot web ...
- 简单的使用httpclient读取网页html例子
public void clientPost(String url) { /* 1 生成 HttpClinet 对象并设置参数*/ HttpClient httpClient=new Http ...
- C++ 回调函数简单示例
回调函数其实就是以函数指针做函数参数传递给另一个函数,在另一个函数执行的时候可以根据函数指针执行回调函数的代码.简单示例,便于理解,防止遗忘. #include <iostream> ty ...
- How Cocoa Beans Grow And Are Harvested Into Chocolate
What is Cocoa Beans Do you like chocolate? Most people do. The smooth, brown candy is deliciously sw ...
- LGOJ1290 欧几里德的游戏
题目链接 P1290 and UVA10368 (双倍经验[虽然标签差距很有趣]) 题目大意 给定两个数\(n\)和\(m\),每次操作可以用较大数减去较小数的正整数倍,不可以减成负数. 先获得一个\ ...
- locate及find查找命令
在文件系统上查找符合条件的文件: 实现工具:locate,find locate: 依赖于事先构建好的索引库: 系统自动实现(周期性任务): 手动更新数 ...
- The sequence and de novo assembly of the giant panda genome.ppt
sequencing:使用二代测序原因:高通量,短序列 不用长序列原因: 1.算法错误率高 2.长序列测序将嵌合体基因错误积累.嵌合体基因:通过重组由来源与功能不同的基因序列剪接而形成的杂合基因 se ...
- 客户端和后台交互日期注意点 sqlite日期字段使用Date类型的情况下
不要直接传递时间类型 一般把时间格式化字符串后传递 不要传递Date().getTime() 毫秒数 非要使用的话需要在后台处理 传递的毫秒数 - TimeZone.getDefault().get ...
- 1)session总结
(1)session的由来: HTTP协议是一种无状态协议,服务器响应完之后就失去了与浏览器的联系,最早,Netscape将cookie引入浏览器,使得数据可以客户端跨页面交换,那么服务器是如何记住众 ...