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的更多相关文章

  1. 学习笔记TF019:序列分类、IMDB影评分类

    序列分类,预测整个输入序列的类别标签.情绪分析,预测用户撰写文字话题态度.预测选举结果或产品.电影评分. 国际电影数据库(International Movie Database)影评数据集.目标值二 ...

  2. AI - TensorFlow - 示例02:影评文本分类

    影评文本分类 文本分类(Text classification):https://www.tensorflow.org/tutorials/keras/basic_text_classificatio ...

  3. 使用RNN进行imdb影评情感识别--use RNN to sentiment analysis

    原创帖子,转载请说明出处 一.RNN神经网络结构 RNN隐藏层神经元的连接方式和普通神经网路的连接方式有一个非常明显的区别,就是同一层的神经元的输出也成为了这一层神经元的输入.当然同一时刻的输出是不可 ...

  4. 基于keras中IMDB的文本分类 demo

      本次demo主题是使用keras对IMDB影评进行文本分类: import tensorflow as tf from tensorflow import keras import numpy a ...

  5. Python深度学习案例1--电影评论分类(二分类问题)

    我觉得把课本上的案例先自己抄一遍,然后将书看一遍.最后再写一篇博客记录自己所学过程的感悟.虽然与课本有很多相似之处.但自己写一遍感悟会更深 电影评论分类(二分类问题) 本节使用的是IMDB数据集,使用 ...

  6. Keras学习笔记(完结)

    使用Keras中文文档学习 基本概念 Keras的核心数据结构是模型,也就是一种组织网络层的方式,最主要的是序贯模型(Sequential).创建好一个模型后就可以用add()向里面添加层.模型搭建完 ...

  7. 我的Keras使用总结(1)——Keras概述与常见问题整理

    今天整理了自己所写的关于Keras的博客,有没发布的,有发布的,但是整体来说是有点乱的.上周有空,认真看了一周Keras的中文文档,稍有心得,整理于此.这里附上Keras官网地址: Keras英文文档 ...

  8. Pytorch文本分类(imdb数据集),含DataLoader数据加载,最优模型保存

    用pytorch进行文本分类,数据集为keras内置的imdb影评数据(二分类),代码包含六个部分(详见代码) 使用环境: pytorch:1.1.0 cuda:10.0 gpu:RTX2070 (1 ...

  9. 用迁移学习创造的通用语言模型ULMFiT,达到了文本分类的最佳水平

    https://www.jqr.com/article/000225 这篇文章的目的是帮助新手和外行人更好地了解我们新论文,我们的论文展示了如何用更少的数据自动将文本分类,同时精确度还比原来的方法高. ...

随机推荐

  1. AutoCAD Civil 3D多版本插件安装包制作

      程序的主要界面如下: 图1 图2 图3 图4   安装包使用Installshield 2016完成.   其中图3是重点,可以选择需要安装的版本,此功能的实现,主要是依靠Installshiel ...

  2. BZOJ5417[Noi2018]你的名字——后缀自动机+线段树合并

    题目链接: [Noi2018]你的名字 题目大意:给出一个字符串$S$及$q$次询问,每次询问一个字符串$T$有多少本质不同的子串不是$S[l,r]$的子串($S[l,r]$表示$S$串的第$l$个字 ...

  3. Dijkstra—校园景点游览问题

    #include<iostream> #include<cstdio> #include<cstring> #define MAX 9999999 using na ...

  4. 洛谷P1083借教室题解

    题目 这个难度感觉并没有那么高,因为这个题暴力也好打,但是比较难想出正解,因为如果你不看标签是很难想到这个题竟然是二分,当然前缀和应该很好想,毕竟让你求的是在某段时间内借教室的和是否满足. 这样我们可 ...

  5. 洛谷p2661信息传递题解

    题目 这个题一眼看上去就是用并查集求最小环. 我们可以设两个数组分别是f,d分别表示该点的爸爸和该点到祖先的距离. 当该点的爸爸等于他时,那他肯定就是祖先. 此时信息就肯定传递完了,此时的整个图中(我 ...

  6. CH2906 武士风度的牛(算竞进阶习题)

    水..... 直接bfs... #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef l ...

  7. 青蛙的约会 POJ - 1061 (exgcd)

    两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特 ...

  8. 【C++】VS2015/VS2017连接Mysql数据库教程

    要给C++程序连接MySQL数据库,分别需要: 安装MySQL Server 下载MySQL Connector/C++ 在IDE中配置依赖 然后就可以在代码中调用API,来连接以及操作数据库. 一. ...

  9. Vert.x系列(三)--ClusteredEventBus源码分析

    前言:因为ClusteredEventBus涉及集群,有必产生网络问题,从而引入了NetServer.ServerID等涉及网络,端口的类.在之前的EventBusImpl中, 使用的数据结构是以ad ...

  10. Spring MVC工作原理 及注解说明

    SpringMVC框架介绍 1) spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面. Spring 框架提供了构建 Web 应用程序的全功 ...