介绍

  前几天,某个公众号发文质疑马蜂窝网站,认为它搬运其它网站的旅游点评,对此,马蜂窝网站迅速地做出了回应。相信大多数关注时事的群众已经了解了整个事情的经过,在这里,我们且不论这件事的是是非非,也不关心它是否是通过爬虫等其他技术手段实现的。本文将会展示一种自动生成旅游点评的技术手段。我们用到的模型为LSTM模型。
  LSTM模型是深度学习中一种重要的模型,全称为Long Short-Term Memory,中文译为长短期记忆网络,是RNN家族中的重要成员,它模拟了人的大脑,具有一定的记忆功能,适合于处理和预测时间序列中间隔和延迟相对较长的重要事件,在翻译语言、控制机器人、图像分析、文档摘要、语音识别图像识别、手写识别、控制聊天机器人、预测疾病、点击率和股票、合成音乐等方面有较多应用。
  在本文中,你将会看到LSTM在自动生成文字(在这里就是旅游点评)方面的应用,如果你感到好奇的话,请继续阅读~

获取数据集

  第一步,就是获取数据集,我们利用Python爬虫来实现。我们需要爬取的旅游评论来自于携程网站上的旅游评论,在本文中,我们以杭州西湖景点的旅游评论为例,页面如下:

我们爬取这些评论中的第1至10页,采用concurrent.futures模块实现并发爬取。完整的Python代码如下:

import requests
import pandas as pd
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED# 评论列表
comments = []# 提取评论,传入参数为网址url
def get_comment(url):global commentstry:# 发送HTTP请求headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 \(KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}r = requests.get(url=url, headers=headers)# 解析网页,定位到评论部分soup = BeautifulSoup(r.text, 'lxml')main_content = soup.find_all('div', class_='comment_single')# 提取评论for para in main_content:comment = para.find('span', class_='heightbox')#print(comment.text)comments.append(comment.text.replace('&quot', ''))except Exception as err:print(err)def main():# 请求网址urls = ["http://you.ctrip.com/sight/hangzhou14/49894-dianping-p%d.html"%x for x in range(1,11)]urls[0] = urls[0].replace('-p1', '')# 利用多线程爬取景点评论executor = ThreadPoolExecutor(max_workers=10)  # 可以自己调整max_workers,即线程的个数# submit()的参数: 第一个为函数, 之后为该函数的传入参数,允许有多个future_tasks = [executor.submit(get_comment, url) for url in urls]# 等待所有的线程完成,才进入后续的执行wait(future_tasks, return_when=ALL_COMPLETED)# 创建DataFrame并保存到csv文件comments_table = pd.DataFrame({'id': range(1, len(comments)+1),'comments': comments})print(comments_table)comments_table.to_csv(r"E://LSTM/hangzhou.csv", index=False)main()

运行完该代码,就会得到hangzhou.csv文件,在这个文件中,我们需要把旅游评论中的文字做一些修改,比如去掉特殊字符,添加掉电,去掉换行,修改个别错别字等。修改完后的csv文件(部分)如下:

得到该csv文件后,我们需要将这些评论(只包含评论)转移到txt文件,以便后续的操作,利用下面的Python
代码即可完成:

import pandas as pd# 读取csv文件
df = pd.read_csv('E://LSTM/hangzhou.csv')['comments']
# 将pandas中的评论修改后,写入txt文件
for item in df:comments = item.replace('\n','').replace('&quot','') \.replace(r' ', '').replace(r'#', '').replace(r'&','') \.replace(r'<', '《').replace(r'>', '》') \.replace(r'↑', '').replace(r'[', '').replace(r']', '') \.replace(r'❤', '')with open('E://LSTM/comments.txt', 'a', encoding='utf-8') as f:f.write(comments)f.write('\n')#print(comments)

txt文件部分如下:

该txt文件一共含有41412个文字。我们将会以这些评论为数据集,在此基础上利用Keras建立LSTM模型,训练完模型后,能自动生成其他的旅游点评。

LSTM模型

  Keras是一个高级的神经网络API,利用它能够轻松地搭建一些复杂的神经网络模型,是一个不错的深度学习框架。对于刚才得到的旅游点评,为了能够生成其他的旅游点评(人类可读),我们将会用到LSTM模型,之所以使用这个模型,是因为LSTM具有长短时记忆功能,能够很好地处理文本中的文字之间的联系,而不是将文字看成是独立的个体。
  在搭建LSTM模型之前,我们需要做一些准备工作。首先我们需要将每个文字对应到一个数字,该模型的输入特征向量为前10个文字对应的数字组成的向量,目标变量为该10个文字的下一个文字对应的数字。该txt文件中一共有1949个文字(包括汉子和标点符号),按照我们的处理模式,共有41402个样本,将这些样本传入到LSTM模型中。我们建立的模型很简单,先是一个LSTM层,利用含有256个LSTM结构,然后是一个Dropout层,能有效防止模型发生过拟合,最后是Softmax层,将它转化为多分类的问题,采用交叉熵作为模型的损失函数。
  训练模型的Python代码如下:

# 搭建简单的LSTM模型用于生成旅游评论
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.callbacks import ModelCheckpoint
from keras.utils import np_utils# 读取txt文件
filename = "E://LSTM/comments.txt"
with open(filename, 'r', encoding='utf-8') as f:raw_text = f.read().lower()# 创建文字和对应数字的字典
chars = sorted(list(set(raw_text)))
#print(chars)
char_to_int = dict((c, i) for i, c in enumerate(chars))
int_to_char = dict((i, c) for i, c in enumerate(chars))
# 对加载数据做总结
n_chars = len(raw_text)
n_vocab = len(chars)
print("总的文字数: ", n_chars)
print("总的文字类别: ", n_vocab)# 解析数据集,转化为输入向量和输出向量
seq_length = 10
dataX = []
dataY = []
for i in range(0, n_chars-seq_length, 1):seq_in = raw_text[i:i + seq_length]seq_out = raw_text[i + seq_length]dataX.append([char_to_int[char] for char in seq_in])dataY.append(char_to_int[seq_out])
n_patterns = len(dataX)
print("Total Patterns: ", n_patterns)
# 将X重新转化为[samples, time steps, features]的形状
X = numpy.reshape(dataX, (n_patterns, seq_length, 1))
# 正则化
X = X/n_vocab
# 对输出变量做one-hot编码
y = np_utils.to_categorical(dataY)# 定义LSTM模型
model = Sequential()
model.add(LSTM(256, input_shape=(X.shape[1], X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
#print(model.summary())# 定义checkpoint
filepath="E://LSTM/weights-improvement-{epoch:02d}-{loss:.4f}.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True, mode='min')
callbacks_list = [checkpoint]
# 训练模型,每批训练128个样本,总共训练1000次
epochs = 1000
model.fit(X, y, epochs=epochs, batch_size=128, callbacks=callbacks_list)

首先让我们看一下模型的结构及参数情况, 使用代码中的print(model.summary())即可,输出如下:

Layer (type)                 Output Shape              Param #
=================================================================
lstm_1 (LSTM)                (None, 256)               264192
_________________________________________________________________
dropout_1 (Dropout)          (None, 256)               0
_________________________________________________________________
dense_1 (Dense)              (None, 1949)              500893
=================================================================
Total params: 765,085
Trainable params: 765,085
Non-trainable params: 0
_________________________________________________________________

虽然是一个很简单的LSTM模型,但也有76万多个参数,深度学习的参数的个数可见一斑~
  运行代码,训练该模型,在训练了漫长的4,5个小时后,在613次的时候,损失值为0.3040,我们就以这个文件作为模型训练的结果,而不是1000次,因为1000次太费时了。文件如下:

请注意删除没用的文件,因为这些生成的文件都很大。

生成旅游点评

  好不容易训练完模型后,下一步,我们将要利用这个模型来生成旅游点评。怎么样,是不是有点期待?生成旅游点评的完整Python如下(我们以输入的句子“杭州西湖天下闻名,西”为例,请注意,每次输入正好10个文字,因为模型训练的输入向量为含10个元素的向量):

# 搭建简单的LSTM模型用于生成旅游评论
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.callbacks import ModelCheckpoint
from keras.utils import np_utils# 读取txt文件
filename = "E://LSTM/comments.txt"
with open(filename, 'r', encoding='utf-8') as f:raw_text = f.read().lower()# 创建文字和对应数字的字典
chars = sorted(list(set(raw_text)))
#print(chars)
char_to_int = dict((c, i) for i, c in enumerate(chars))
int_to_char = dict((i, c) for i, c in enumerate(chars))
# 对加载数据做总结
n_chars = len(raw_text)
n_vocab = len(chars)
print("总的文字数: ", n_chars)
print("总的文字类别: ", n_vocab)# 解析数据集,转化为输入向量和输出向量
seq_length = 10
dataX = []
dataY = []
for i in range(0, n_chars-seq_length, 1):seq_in = raw_text[i:i + seq_length]seq_out = raw_text[i + seq_length]dataX.append([char_to_int[char] for char in seq_in])dataY.append(char_to_int[seq_out])
n_patterns = len(dataX)
print("Total Patterns: ", n_patterns)
# 将X重新转化为[samples, time steps, features]的形状
X = numpy.reshape(dataX, (n_patterns, seq_length, 1))
# 正则化
X = X/n_vocab
# 对输出变量做one-hot编码
y = np_utils.to_categorical(dataY)# 定义LSTM模型
model = Sequential()
model.add(LSTM(256, input_shape=(X.shape[1], X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')# 导入训练完后的文件
filename = "E://LSTM/weights-improvement-613-0.3040.hdf5"
model.load_weights(filename)
# 示例的输入句子
input = '杭州西湖天下闻名,西'
pattern = [char_to_int[value] for value in input]
print("输入:")
print(''.join([int_to_char[value] for value in pattern]))
print("输出:")
# 生成1000个文字
for i in range(1000):x = numpy.reshape(pattern, (1, len(pattern), 1))x = x / float(n_vocab)prediction = model.predict(x, verbose=0)index = numpy.argmax(prediction)result = int_to_char[index]print(result, end='')seq_in = [int_to_char[value] for value in pattern]pattern.append(index)pattern = pattern[1:len(pattern)]
print("\n生成完毕。")

运行该代码,就能看到生成的文字如下:

输入:
杭州西湖天下闻名,西
输出:
湖一年四季特色纷呈,西湖有湖光山色交相辉应,既可看湖又可看山,西湖上的桥也是兼具南北特色,长桥不长,断桥不断。
西湖古迹遍布,山水秀丽,景色宜人,西湖处处有胜景。最著名的西湖十景,西湖十景”是指浙江省杭州市着名旅游景点西湖上的十处特色风景,分别是苏堤春晓、曲苑风荷、平湖秋月、断桥残雪、柳浪闻莺、花港观鱼、雷峰夕照、双峰插云、南屏晚钟、三潭印月等十个景点是杭州游览的热点,不用按照目前的时髦话说什么“非看不可”、“非去不可”,但是,如果去了杭州不看这些景点,不看这些景点的碑刻,就有点可惜了,特别是有康熙爷、乾隆爷的亲笔题词,不去看看,多少会对老祖宗的“大不敬”。
如果天气晴朗下午五点以后去西湖,如果拍视频你就会拍到天蓝蓝水蓝蓝的西湖和夕阳西下渐黄昏的完美,西湖边上有小凳子可以坐下来静静的欣赏西湖美景也可和同行的伙伴聊聊接下来的行程,目的是等待晚上更值得期待的音乐喷泉,得早早坐下来否则就看不到了,看喷泉不允许站着凳子坐满其余人站凳子后面。
西湖游船是游西湖必不可少的。另外早晨可以早点去,人少,而且凉爽。花港观鱼的景色也是不错。雷峰塔就看你需求了,可以俯瞰整个西湖(其实去雷峰塔也是为了看西湖吧,雷峰塔本身貌似没什么看的)吃饭的话,别在景区吃,强烈推荐去弄堂里。好吃又便宜。
8月份出差路过杭州,可以轻松的偷闲半天,顺便预约了离西湖比较近便的酒店入住。8月底的清晨已经有了丝丝的凉意,顺着西湖边开始溜达。早上人还是比较少,本地起来锻炼的大爷大妈比较多,有蘸水在地上练字的,有在小公园练嗓子的,还有坐在长条凳上练二胡的。9点多点,游客开始多了,各种游船排队等候,暑假期间带小孩匆匆而过的人也不少,基本都是到此一游,很少有仔细的欣赏和解说景点的出处。乘凉的地方还是不少,但是蚊子也多的吓人。苏堤的景色不错,特别是两边的高树遮挡了大多数的阳光,即使在这里溜达也不会觉得热,如果时间允许的话,建议溜达过去,步行约30分钟左右,南边的出口还有苏东坡博物馆,比较小,免费开放。
西湖的范围蛮大的,从北山路(北山路上的老建筑,浙江博物馆,断桥残雪,锦带桥,保俶塔,楼外楼,孤山,西冷印社,平湖秋月等。)到南线景区(南山路,西湖天地,御码头,钱王祠,柳浪闻莺,万松书院,长桥,南屏晚钟,净慈寺,雷锋塔太子湾等)以及三堤,外西湖,西里湖等,小南湖,小瀛洲,从白堤_苏堤_曲院风荷_杨公堤_鵒鸪湾_茅家埠。飞来峰景
生成完毕。

让我们来看一下这段生成的文字,首先,这段文字的可读性还是很高的,基本上人类能够理解,其次,与原文相对比,这段文字并不是一味地抄袭原文,而是有选择地将原文件中的旅游点评组合起来,虽然每部分的旅游点评与原先的相差不多,但重新组合后,是能够生成新的旅游点评的,并不算真正意义上的抄袭。
  用LSTM训练出来的模型生成的文本,是能够作为新的旅游点评的,并不是完全的抄袭,但是对于未在原文中出现的输入向量,可能训练出来的效果就不会太理想,这是需要改进的地方。

总结

  本文纯属自娱自乐,如果不当之处,还望大家批评指正~~
  当然,对于该项目,还有一些值得改进的地方,比如数据集不够大,这个可以爬取更多的评论;数据预处理过于简单,仅仅做了文字与向量的一一对应以及输入向量的正则化;模型过于简单,读者可以尝试搭建多个LSTM层或其他结构;模型训练过于耗时,可以尝试GPU或改进模型结构或数据预处理方式,等等等等。希望读者在阅读完本文后,能对LSTM模型在文字生成方面有一定的了解,欢迎拥抱LSTM~~

参考文献

Text Generation With LSTM Recurrent Neural Networks in Python with Keras: https://machinelearningmastery.com/text-generation-lstm-recurrent-neural-networks-python-keras/

RNN入门(三)利用LSTM生成旅游点评相关推荐

  1. Excel 2010 VBA 入门 104 利用VBA生成图表

    目录 示例 代码 ChartObjects集合和ChartObject对象 数据系列(Series)对象 添加图表的其他方法 1.通过添加Chart对象添加图表 2.通过Shapes集合的AddCha ...

  2. 【RNN入门到实战】LSTM从入门到实战——实现空气质量预测

    摘要 LSTM是一种时间递归神经网络,它出现的原因是为了解决RNN的一个致命的缺陷.RNN在处理长期依赖(时间序列上距离较远的节点)时,因为计算距离较远的节点之间的联系时会涉及雅可比矩阵的多次相乘,会 ...

  3. pytorch利用rnn通过sin预测cos 利用lstm预测手写数字

    一.利用rnn通过sin预测cos 1.首先可视化一下数据 import numpy as np from matplotlib import pyplot as plt def show(sin_n ...

  4. Vivado 2018.3入门教程(三):生成比特流文件+硬件连接

    这是我的Vivado 2018.3入门教程(三):生成比特流文件+硬件连接 我的Vivado 2018.3入门教程大致分为四个部分: Vivado 2018.3入门教程(一):创建工程+新建源文件. ...

  5. 【思维导图】利用LSTM(长短期记忆网络)来处理脑电数据

    文章来源| 脑机接口社区群友 认知计算_茂森的授权分享 在此非常感谢 认知计算_茂森! 本篇文章主要通过思维导图来介绍利用LSTM(长短期记忆网络)来处理脑电数据. 文章的内容来源于社区分享的文章&l ...

  6. 深度学习与自然语言处理教程(5) - 语言模型、RNN、GRU与LSTM(NLP通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/36 本文地址:https://www.showmeai.tech/article-d ...

  7. 利用LSTM(长短期记忆网络)来处理脑电数据

    目录 LSTM 原理介绍 LSTM的核心思想 一步一步理解LSTM 代码案例 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区 .QQ交流群:903290195 Rose小哥今天介绍一下用LS ...

  8. 深度学习(十一)RNN入门学习

    RNN入门学习 原文地址:http://blog.csdn.net/hjimce/article/details/49095371 作者:hjimce 一.相关理论 RNN(Recurrent Neu ...

  9. .Net 3.5 Remoting编程入门三

    VS2008 .Net 3.5 Remoting编程入门三 信道 什么是信道?信道有哪些类型呢? 信道顾名思意就是通信的通道.就想那些宣传标语说的,"要想富,先修路!".同理,要学 ...

最新文章

  1. UVa12412 - A Typical Homework (a.k.a Shi Xiong Bang Bang Mang)
  2. 新DNS木马可感染整个局域网内计算机
  3. 爬虫基本库的使用---urllib库
  4. 3.游戏优化(CCSpriteBatchNode)
  5. VS2019 更新MSDN并创建快捷方式
  6. 作者:林春雨,男,现任北京拓尔思信息技术股份有限公司高级副总裁、助理研究员。...
  7. 学习python入门的个人建议及资料
  8. 送给程序员:关于性格内向者的10个误解(转)
  9. iOS 警告收录及科学快速的消除方法
  10. javascript之js实现简单的无缝轮播图(可调节方向)
  11. 李昌镐究竟是不是神?
  12. pycharm 无法安装模块 nothing to show
  13. vscode 折叠/展开所有区域代码快捷键
  14. linux操作系统拼音,linux怎么读 解读linux的拼音笔顺笔画顺序怎么写!
  15. 拔掉MacBookPro,用8GB树莓派4工作一天,体验原来是这样的
  16. Go语言攻略:“面向对象”
  17. OFD文件怎么转PDF?ofd文件转换为pdf格式教程
  18. JavaScript中查找关键词
  19. 组策略 控制台登录计算机用用户,更方便的管理计算机!Windows组策略应用全攻略一...
  20. 百度开放平台调用人脸识别等api问题

热门文章

  1. js-判断输入值是不是数字、字符串
  2. KRnano打开黑屏: FATAL ERROR,【解决办法】
  3. json格式问题解决方式!
  4. 第19天 写一个方法验证国内车牌号是否正确
  5. Sql Server 2008 R2 清理内存的三种方法
  6. Gson的JsonParser使用
  7. BZOJ4416: [Shoi2013]阶乘字符串
  8. R数据加工厂-plyr包
  9. 机器学习:最大熵模型
  10. CUDA + cuDNN + tensorflow-gpu 安装