IMDB影评倾向分类 - N-Gram
catalogue
. 数据集
. 模型设计
. 训练
1. 数据集
0x1: IMDB影评数据
本数据库含有来自IMDB的25,000条影评,被标记为正面/负面两种评价
from keras.datasets import imdb (X_train, y_train), (X_test, y_test) = imdb.load_data(path="imdb_full.pkl",
nb_words=None,
skip_top=,
maxlen=None,
test_split=0.1)
seed=,
start_char=,
oov_char=,
index_from=) . path:如果你在本机上已有此数据集(位于'~/.keras/datasets/'+path),则载入。否则数据将下载到该目录下
. nb_words:整数或None,要考虑的最常见的单词数,任何出现频率更低的单词将会被编码到0的位置。
. skip_top:整数,忽略最常出现的若干单词,这些单词将会被编码为0
. maxlen:整数,最大序列长度,任何长度大于此值的序列将被截断
. seed:整数,用于数据重排的随机数种子
. start_char:字符,序列的起始将以该字符标记,默认为1因为0通常用作padding
. oov_char:字符,因nb_words或skip_top限制而cut掉的单词将被该字符代替
. index_from:整数,真实的单词(而不是类似于start_char的特殊占位符)将从这个下标开始
返回值两个Tuple,(X_train, y_train), (X_test, y_test),其中
X_train和X_test:序列的列表,每个序列都是词下标的列表。如果指定了nb_words,则序列中可能的最大下标为nb_words-。如果指定了maxlen,则序列的最大可能长度为maxlen
y_train和y_test:为序列的标签,是一个二值list
0x2: 数据预处理
影评已被预处理为词下标构成的序列,单词的下标基于它在数据集中出现的频率标定,例如整数3所编码的词为数据集中第3常出现的词,类似下面这张图

h的词频在数据集中的频率排名第一,所以它的编码为1
X_train[]
[, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] y_train[]
将语料集转化为一个词频组合的编号集
0x2: N-Gram生成
需要注意的是,kera的dataset默认采用1-Gram的分组方式,如果我们需要使用2-Gram、N-Gram等情况,需要在预处理阶段进行拼接
if ngram_range > :
print('Adding {}-gram features'.format(ngram_range))
# Create set of unique n-gram from the training set.
ngram_set = set()
for input_list in X_train:
for i in range(, ngram_range + ):
set_of_ngram = create_ngram_set(input_list, ngram_value=i)
ngram_set.update(set_of_ngram)
print('ngram_set.pop')
print(ngram_set.pop())

将1-Gram进行"两两组合",得到2-Gram,同时组合后的2-Gram需要再次进行index编号,编号的起始就从max_features开始,因为在1-Gram的时候,我们已经把0-max_features的编号都使用过了
但是要注意一个问题,2-Gram对应的组合数量和1-Gram是几何倍数增加的,对计算和内存的要求也成倍提高了
0x3: 填充序列pad_sequences
得到的数据是一个2D的数据,shape是
X_train shape: (, )
X_test shape: (, )
2500是max_features,即我们只从训练语料库中选取排名前2500词频的词,400代表maxlen,我们认为对话的长度最长为400,把所有不足400的都padding到400长度
Relevant Link:
https://github.com/fchollet/keras/blob/master/examples/imdb_fasttext.py
2. 模型设计
0x1: 嵌入层
model.add(Embedding(max_features,
embedding_dims,
input_length=maxlen))
输入数据的维度就是max_features,即我们选取的词频列表中排名前max_features的词频,输入维度为embedding_dims = 50
0x2: 池化层 - 池化是一种低损降维的好方法
在通过卷积获得了特征(features)之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以把所有解析出来的特征关联到一个分类器,例如softmax分类器,但计算量非常大。例如:对于一个96X96像素的图像,假设我们已经通过8X8个输入学习得到了400个特征。而每一个卷积都会得到一个(96 − 8 + 1) * (96 − 8 + 1) = 7921的结果集,由于已经得到了400个特征,所以对于每个样例(example)结果集的大小就将达到892 * 400 = 3,168,400 个特征。这样学习一个拥有超过3百万特征的输入的分类器是相当不明智的,并且极易出现过度拟合(over-fitting).
所以就有了pooling这个方法,本质上是把特征维度区域的一部分求个均值或者最大值,用来代表这部分区域。如果是求均值就是mean pooling,求最大值就是max pooling
之所以这样做,拿图像识别举例子,是因为:我们之所以决定使用卷积后的特征是因为图像具有一种“静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计。这个均值或者最大值就是一种聚合统计的方法。
另外,如果人们选择图像中的连续范围作为池化区域,并且只是池化相同(重复)的隐藏单元产生的特征,那么,这些池化单元就具有平移不变性(translation invariant)。这就意味着即使图像经历了一个小的平移之后,依然会产生相同的(池化的)特征
model.add(GlobalAveragePooling1D())
Relevant Link:
https://keras-cn.readthedocs.io/en/latest/layers/embedding_layer/
http://www.cnblogs.com/bzjia-blog/p/3415790.html
https://keras-cn.readthedocs.io/en/latest/layers/pooling_layer/
3. 训练
'''This example demonstrates the use of fasttext for text classification
Based on Joulin et al's paper:
Bags of Tricks for Efficient Text Classification
https://arxiv.org/abs/1607.01759
Results on IMDB datasets with uni and bi-gram embeddings:
Uni-gram: 0.8813 test accuracy after epochs. 8s/epoch on i7 cpu.
Bi-gram : 0.9056 test accuracy after epochs. 2s/epoch on GTX 980M gpu.
''' from __future__ import print_function
import numpy as np
np.random.seed() # for reproducibility from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Embedding
from keras.layers import GlobalAveragePooling1D
from keras.datasets import imdb def create_ngram_set(input_list, ngram_value=):
"""
Extract a set of n-grams from a list of integers.
>>> create_ngram_set([, , , , , ], ngram_value=)
{(, ), (, ), (, ), (, )}
>>> create_ngram_set([, , , , , ], ngram_value=)
[(, , ), (, , ), (, , ), (, , )]
"""
return set(zip(*[input_list[i:] for i in range(ngram_value)])) def add_ngram(sequences, token_indice, ngram_range=):
"""
Augment the input list of list (sequences) by appending n-grams values.
Example: adding bi-gram
>>> sequences = [[, , , ], [, , , , ]]
>>> token_indice = {(, ): , (, ): , (, ): }
>>> add_ngram(sequences, token_indice, ngram_range=)
[[, , , , , ], [, , , , , , ]]
Example: adding tri-gram
>>> sequences = [[, , , ], [, , , , ]]
>>> token_indice = {(, ): , (, ): , (, ): , (, , ): }
>>> add_ngram(sequences, token_indice, ngram_range=)
[[, , , , ], [, , , , , , ]]
"""
new_sequences = []
for input_list in sequences:
new_list = input_list[:]
for i in range(len(new_list) - ngram_range + ):
for ngram_value in range(, ngram_range + ):
ngram = tuple(new_list[i:i + ngram_value])
if ngram in token_indice:
new_list.append(token_indice[ngram])
new_sequences.append(new_list) return new_sequences # Set parameters:
# ngram_range = will add bi-grams features
ngram_range =
max_features =
maxlen =
batch_size =
embedding_dims =
nb_epoch = print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(
path="/home/zhenghan/keras/imdb_full.pkl",
nb_words=max_features
) # truncate the dataset
truncate_rate = 0.4
X_train = X_train[:int(len(X_train) * truncate_rate)]
y_train = y_train[:int(len(y_train) * truncate_rate)]
X_test = X_test[:int(len(X_test) * truncate_rate)]
y_test = y_test[:int(len(y_test) * truncate_rate)] print("X_train[0]")
print(X_train[])
print('y_train[0]')
print(y_train[]) print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
print('Average train sequence length: {}'.format(np.mean(list(map(len, X_train)), dtype=int)))
print('Average test sequence length: {}'.format(np.mean(list(map(len, X_test)), dtype=int))) if ngram_range > :
print('Adding {}-gram features'.format(ngram_range))
# Create set of unique n-gram from the training set.
ngram_set = set()
for input_list in X_train:
for i in range(, ngram_range + ):
set_of_ngram = create_ngram_set(input_list, ngram_value=i)
ngram_set.update(set_of_ngram)
print('ngram_set.pop')
print(ngram_set.pop()) # Dictionary mapping n-gram token to a unique integer.
# Integer values are greater than max_features in order
# to avoid collision with existing features.
start_index = max_features +
token_indice = {v: k + start_index for k, v in enumerate(ngram_set)}
indice_token = {token_indice[k]: k for k in token_indice} # max_features is the highest integer that could be found in the dataset.
max_features = np.max(list(indice_token.keys())) +
print('max_features: ')
print(max_features) # Augmenting X_train and X_test with n-grams features
X_train = add_ngram(X_train, token_indice, ngram_range)
X_test = add_ngram(X_test, token_indice, ngram_range) print("X_train[0]")
print(X_train[])
print('X_test[0]')
print(X_test[]) print('Average train sequence length: {}'.format(np.mean(list(map(len, X_train)), dtype=int)))
print('Average test sequence length: {}'.format(np.mean(list(map(len, X_test)), dtype=int))) print('Pad sequences (samples x time)')
X_train = sequence.pad_sequences(X_train, maxlen=maxlen)
X_test = sequence.pad_sequences(X_test, maxlen=maxlen)
print('X_train shape:', X_train.shape)
print('X_test shape:', X_test.shape) print('Build model...')
model = Sequential() # we start off with an efficient embedding layer which maps
# our vocab indices into embedding_dims dimensions
model.add(Embedding(max_features,
embedding_dims,
input_length=maxlen)) # we add a GlobalAveragePooling1D, which will average the embeddings
# of all words in the document
model.add(GlobalAveragePooling1D()) # We project onto a single unit output layer, and squash it with a sigmoid:
model.add(Dense(, activation='sigmoid')) model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy']) model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, y_test))

Relevant Link:
https://keras-cn.readthedocs.io/en/latest/other/datasets/
https://keras-cn.readthedocs.io/en/latest/preprocessing/sequence/
Copyright (c) 2017 LittleHann All rights reserved
IMDB影评倾向分类 - N-Gram的更多相关文章
- 学习笔记TF019:序列分类、IMDB影评分类
序列分类,预测整个输入序列的类别标签.情绪分析,预测用户撰写文字话题态度.预测选举结果或产品.电影评分. 国际电影数据库(International Movie Database)影评数据集.目标值二 ...
- AI - TensorFlow - 示例02:影评文本分类
影评文本分类 文本分类(Text classification):https://www.tensorflow.org/tutorials/keras/basic_text_classificatio ...
- 使用RNN进行imdb影评情感识别--use RNN to sentiment analysis
原创帖子,转载请说明出处 一.RNN神经网络结构 RNN隐藏层神经元的连接方式和普通神经网路的连接方式有一个非常明显的区别,就是同一层的神经元的输出也成为了这一层神经元的输入.当然同一时刻的输出是不可 ...
- 基于keras中IMDB的文本分类 demo
本次demo主题是使用keras对IMDB影评进行文本分类: import tensorflow as tf from tensorflow import keras import numpy a ...
- Python深度学习案例1--电影评论分类(二分类问题)
我觉得把课本上的案例先自己抄一遍,然后将书看一遍.最后再写一篇博客记录自己所学过程的感悟.虽然与课本有很多相似之处.但自己写一遍感悟会更深 电影评论分类(二分类问题) 本节使用的是IMDB数据集,使用 ...
- Keras学习笔记(完结)
使用Keras中文文档学习 基本概念 Keras的核心数据结构是模型,也就是一种组织网络层的方式,最主要的是序贯模型(Sequential).创建好一个模型后就可以用add()向里面添加层.模型搭建完 ...
- 我的Keras使用总结(1)——Keras概述与常见问题整理
今天整理了自己所写的关于Keras的博客,有没发布的,有发布的,但是整体来说是有点乱的.上周有空,认真看了一周Keras的中文文档,稍有心得,整理于此.这里附上Keras官网地址: Keras英文文档 ...
- Pytorch文本分类(imdb数据集),含DataLoader数据加载,最优模型保存
用pytorch进行文本分类,数据集为keras内置的imdb影评数据(二分类),代码包含六个部分(详见代码) 使用环境: pytorch:1.1.0 cuda:10.0 gpu:RTX2070 (1 ...
- 用迁移学习创造的通用语言模型ULMFiT,达到了文本分类的最佳水平
https://www.jqr.com/article/000225 这篇文章的目的是帮助新手和外行人更好地了解我们新论文,我们的论文展示了如何用更少的数据自动将文本分类,同时精确度还比原来的方法高. ...
随机推荐
- Spring MVC 使用介绍(一)—— 概述
一.Web MVC简介 1.经典的MVC架构 存在的问题:1.控制器负责流程控制.请求数据整理与校验.模型与视图选择等功能,过于复杂.2.模型层没有进行分层设计 2.改进的MVC设计 1)控制器功能拆 ...
- D - Mayor's posters POJ - 2528 离散化+线段树 区间修改单点查询
题意 贴海报 最后可以看到多少海报 思路 :离散化大区间 其中[1,4] [5,6]不能离散化成[1,2] [2,3]因为这样破坏了他们的非相邻关系 每次离散化区间 [x,y]时 把y+1点也加入 ...
- Number Sequence POJ - 1019 递推 数学
题意 1 12 123 1234 12345 ....这样的序列 问第n位数字是几 是数字! 1-9! 思路:递推关系 主要是位数的计算 用a[i]=a[i-1]+(int)log10((do ...
- 洛谷P1434滑雪题解及记忆化搜索的基本步骤
题目 滑雪是一道dp及记忆化搜索的经典题目. 所谓记忆化搜索便是在搜索的过程中边记录边搜索的一个算法. 当下次搜到这里时,便直接使用. 而且记忆化搜索一定要满足无后效性,为什么呢,因为如果不满足无后效 ...
- 搭建gogs常见问题
1.无法连接ssh,显示connection refuse. 原因是“custom/conf/app.ini”没有开启ssh功能,改为以下配置就行了 START_SSH_SERVER = true ...
- windows10配置virtualenv
1.从官网下载pip:https://pypi.python.org/pypi/pip/,下载完成之后,解压到一个文件夹,用CMD控制台进入解压目录,输入:python setup.py instal ...
- jquery扩展写法
如何制作自己的Jquery插件,内容参考学习了网上的讲解,如下 使用这两个方法 jQuery.fn.extend(object) jQuery.extend(object) jQuery.extend ...
- SAM练习记录
SAM练习记录 洛谷 P1368 工艺 其实是最小表示法裸题 倍长后建SAM跑最小的边走|S|步即可 Code CF 235 C. Cyclical Quest 对主串建SAM 然后每个串倍长,跑的时 ...
- c# WebApi之解决跨域问题:Cors
什么是跨域问题 出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容.由于这个原因,我们不同站点之间的数据访问会被拒绝. Cors解决跨域问 ...
- vue层级关系的数据管理
项目背景:为一些有层级关系的数据管理做一套后台管理系统,例如一个小区,里面是有许多楼,楼里有许多层,每一层有许多不同的房······,现在就是要实现对这些数据进行增删改查操作. 1.Tree(树形组件 ...