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 这篇文章的目的是帮助新手和外行人更好地了解我们新论文,我们的论文展示了如何用更少的数据自动将文本分类,同时精确度还比原来的方法高. ...
随机推荐
- url.openconnection() 设置超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "30000"); System.setP ...
- AIM Tech Round 4 Div. 1
A:显然最优方案是对所形成的置换的每个循环排个序. #include<iostream> #include<cstdio> #include<cmath> #inc ...
- springboot 学习
参考:http://www.cnblogs.com/sam-uncle/p/8796212.html spring boot 系列之一:spring boot 入门 注意:main启动类和contro ...
- 接口压测初识java GC
1.先用Spring Boot 搭建 web 服务,构建api 服务 @RequestMapping("/index") @ResponseBody public String i ...
- IDEA 新建 module
maven项目可以创建多个module,在IDEA中具体操作 1.在已经建好的maven项目上右键 2.新建: 效果如下: 这时在子pom.xml中 <parent> <artifa ...
- 爬虫_糗事百科(scrapy)
糗事百科scrapy爬虫笔记 1.response是一个'scrapy.http.response.html.HtmlResponse'对象,可以执行xpath,css语法来提取数据 2.提取出来的数 ...
- Hdoj 4508.湫湫系列故事——减肥记I 题解
Problem Description 对于吃货来说,过年最幸福的事就是吃了,没有之一! 但是对于女生来说,卡路里(热量)是天敌啊! 资深美女湫湫深谙"胖来如山倒,胖去如抽丝"的道 ...
- ViewHolder模式的简洁写法
大家通常怎么写ViewHolder呢? ViewHolder holder = null; if(convertView == null){ convertView = mInflater.infla ...
- Dynamic CRM 2015学习笔记(5)CRM 2015 导入 OData Query Designer 解决方案
以前一直使用OData Query Designer来生成.验证odata查询字符串,本想把它导入到CRM 2015的环境里,但报错: 到MSDN上发现太老版本的solution确实不能再导入到crm ...
- gulp与webpack的区别
gulp gulp强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并.雪碧图.启动server.版本控制等),然后定义执行顺序,来让gulp执行这 ...