keras 基础入门整理

第一部分 文本与序列处理

1.简介

在进行自然语言处理之前,需要对文本进行处理。 本文介绍keras提供的预处理包keras.preproceing下的text与序列处理模块sequence模块

2 text模块提供的方法

text_to_word_sequence(text,fileter) 可以简单理解此函数功能类str.split one_hot(text,vocab_size) 基于hash函数(桶大小为vocab_size),将一行文本转换向量表示

3 text.Tokenizer类

这个类用来对文本中的词进行统计计数,生成文档词典,以支持基于词典位序生成文本的向量表示。 init(num_words) 构造函数,传入词典的最大值

3.1 成员函数

fit_on_text(texts) 使用一系列文档来生成token词典,texts为list类,每个元素为一个文档。 texts_to_sequences(texts) 将多个文档转换为word下标的向量形式,shape为[len(texts),len(text)] texts_to_matrix(texts) 将多个文档转换为矩阵表示,shape为[len(texts),num_words]

3.2 成员变量

document_count 处理的文档数量 word_index 一个dict,保存所有word对应的编号id,从1开始 word_counts 一个dict,保存每个word在所有文档中出现的次数 word_docs 一个dict,保存每个word出现的文档的数量 index_docs 一个dict,保存word的id出现的文档的数量

4.示例

import keras.preprocessing.text as T
from keras.preprocessing.text import Tokenizer
import keras
print(keras.__version__)
# text1='some thing to eat'
# text2='some thing to drink'
# text是经过分词处理的语句,分隔符要与Tokenizer中split选择相同
text1='我 爱 北京'
text2='我 爱 北京 天安门'
texts=[text1,text2]

print (T.text_to_word_sequence(text1))  #['some', 'thing', 'to', 'eat']
#基于hash函数(桶大小为n,n: int. Size of vocabulary),将一行文本转换向量表示
print (T.one_hot(text1,n=5))  #[7, 9, 3, 4]
print (T.one_hot(text2,n=10))  #[7, 9, 3, 1]
#num_words为词的总长度,这里暂定为10
tokenizer = Tokenizer(num_words=10,split=" ")#num_words:None或整数,处理的最大单词数量。少于此数的单词丢掉

# tokenizer.fit_on_text(texts)
tokenizer.fit_on_texts(texts)

# print (tokenizer.word_count )#[('some', 2), ('thing', 2), ('to', 2), ('eat', 1), ('drink', 1)]
print(tokenizer.word_counts)
print (tokenizer.word_index )#{'some': 1, 'thing': 2,'to': 3 ','eat': 4, drink': 5}
print (tokenizer.word_docs) #{'some': 2, 'thing': 2, 'to': 2, 'drink': 1,  'eat': 1}
print (tokenizer.index_docs )#{1: 2, 2: 2, 3: 2, 4: 1, 5: 1}
print("#"*5+"转化词向量"+"#"*5)
# print (tokenizer.text_to_sequences(texts) )#[[1, 2, 3, 4], [1, 2, 3, 5]]

# num_words=多少会影响下面的结果,行数=num_words

print (tokenizer.texts_to_sequences(texts) )#[[1, 2, 3, 4], [1, 2, 3, 5]]
print (tokenizer.texts_to_matrix(texts) )#
2.2.2
['我', '爱', '北京']
[4, 1, 2]
[9, 6, 7, 4]
OrderedDict([('我', 2), ('爱', 2), ('北京', 2), ('天安门', 1)])
{'我': 1, '爱': 2, '北京': 3, '天安门': 4}
defaultdict(<class 'int'>, {'北京': 2, '我': 2, '爱': 2, '天安门': 1})
defaultdict(<class 'int'>, {3: 2, 1: 2, 2: 2, 4: 1})
#####转化词向量#####
[[1, 2, 3], [1, 2, 3, 4]]
[[0. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
 [0. 1. 1. 1. 1. 0. 0. 0. 0. 0.]]

第二部分 Keras中的神经网络层组件简介

1 简介 在对Keras的简单使用之后,本文对Keras提供的对各种层的抽象进行相对全面的概括,以对Keras有更全面的认识。 2 基础常用层

名称

作用

原型参数

Dense

实现全连接层

Dense(units,activation,use_bias=True, kernel_initializer=’glorot_uniform’, bias_initializer=’zeros’)

Activation

对上层输出应用激活函数

Activation(activation)

Dropout

对上层输出应用dropout以防止过拟合

Dropout(ratio)

Flatten

对上层输出一维化

Flatten()

Reahape

对上层输出reshape

Reshape(target_shape)

Permute

对输入的维度按照指定的顺序交换并重排数据

Permute(dims)

RepeatVector

将输入重复若干次后进行输出

RepeatVector(n)

Lambda

对输入施加TF/TH表达式后输出

Lambda(function, output_shape,arguments=None)

Masking

屏蔽指定的序列值

Masking(mask_value=0.0)

PS1:Dense()参数说明

名称

说明

units

层中单元数,也是输出维度

activation

激活函数

use_bias

是否使用偏置

kernel_initializer

权值初始化方法

bias_initalizer

偏置初始化方法

kernel_regularizer

权值规范化方法

bias_regularizer

偏置规范化方法

activity_regularizer

kernel_constraints

权值约束

bias_constraints

偏置约束

PS2: 预置激活函数/初始化器/正则化器说明

激活函数

初始化器

正则化器

softmax

Zeros 全0

l1

elu

Ones 全1

l2

softplus

Constant 常数

l1_l2

softsign

RandomNormal 正态分布

relu

RandomUniform 平均分布

tanh

TruncatedNormal 无尾正态

sigmoid

Orthogonal 正交矩阵

hard_sigmoid

Identity 单位矩阵

linear

glorot_normal

he_normal

he_uniform

3 巻积层

名称

作用

原型参数

Conv1D

一维巻积层

Conv1D(filters, kernel_size, strides=1, padding=’valid’)

Conv2D

二维巻积层

Conv2D(filters, kernel_size, strides=(1, 1), padding=’valid’)

参数说明

名称

说明

filters

卷积核的数目(即输出的维度)

kernel_size

卷积核的宽度和长度。如为单个整数,表示在各个空间维度的相同长度

strides

为卷积的步长。如为单个整数,则表示在各个空间维度的相同步长

padding

补0策略,为“valid”, “same”

activation

data_format

channels_first或channels_last之一,代表图像的通道维的位置,默认为channels_last

use_bias

kernel_initializer

bias_initializer

kernel_regularizer

bias_regularizer

activity_regularizer

kernel_constraints

bias_constraints

4 池化层

名称

作用

原型参数

MaxPooling2D

二维最大池化层

MaxPooling2D(pool_size=(2, 2), strides=None, padding=’valid’, data_format=None)

AveragePooling2D

平均最大池化层

AveragePooling2D(pool_size=(2, 2), strides=None, padding=’valid’)

5 循环层

名称

作用

原型参数

SimpleRNN

全连接RNN网络

SimpleRNN(units, activation=’tanh’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’,dropout=0.0, recurrent_dropout=0.0))

GRU

门限循环单元层

GRU(units, activation=’tanh’, recurrent_activation=’hard_sigmoid’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’, dropout=0.0, recurrent_dropout=0.0)

LSTM

长短期记忆模型层

LSTM(units, activation=’tanh’, recurrent_activation=’hard_sigmoid’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’, unit_forget_bias=True, dropout=0.0, recurrent_dropout=0.0)

6 嵌入层

名称

作用

原型参数

Embedding

嵌入层将输入中的整数转换为向量,导致原维度+1

EmbeddingEmbedding(input_dim, output_dim, embeddings_initializer=’uniform’, embeddings_regularizer=None, activity_regularizer=None, embeddings_constraint=None, mask_zero=False, input_length=None)

参数说明: input_dim: 字典长度,即输入数据最大下标+1 output_dim:全连接嵌入的维度 input_length:当输入序列的长度固定时,该值为其长度。如果要在该层后接Flatten层,然后接Dense层,则必须指定该参数,否则Dense层的输出维度无法自动推断。

7 局部连接层

名称

作用

原型参数

LocallyConnected2D

不进行权重共享的2维层

LocallyConnected2D(filters, kernel_size, strides=(1, 1), padding=’valid’)

8 规范化层

名称

作用

原型参数

BatchNormalization

对批次数据进行规范化

BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer=’zeros’, gamma_initializer=’ones’, moving_mean_initializer=’zeros’, moving_variance_initializer=’ones’)

9 噪声层

名称

作用

原型参数

GaussianNoise

为数据施加0均值,标准差为stddev的加性高斯噪声

GaussianNoise(stddev)

GaussianDropout

为输入施加以1为均值,标准差为sqrt(rate/(1-rate)的乘性高斯噪声

GaussianDropout(rate)

10 高级激活层

名称

作用

原型参数

LeakyReLU

ReLU激活的改进层

LeakyReLU(alpha=0.3)

PReLU

参数化的ReLU

ELU

指数参数化ReLU

ThresholdedReLU

阀值化ReLU

11 Wraaper层

名称

作用

原型参数

TimeDistributed

TimeDistributed(layer)

Bidirectional

双向RNN包装器

Bidirectional(layer, merge_mode=’concat’, weights=None)

参考文献:https://keras-cn.readthedocs.io/en/latest/

神经网络的使用

简介

keras提供了两种模型,一种是Sequential,译做序列型模型。另一种是Functional,译做函数型模型。二者可以从使用形式来区分,序列模型可以看做是面向对象的方法,一系列对象协作完成任务。函数模型则是一系列的过程调用来完成任务。

序列模型的概念比较简单,就是把一些基础神经网络层组件一个个串联起来形成一个完整的模型,在此模型上进行训练,从而完成学习任务。 函数模型就是一系列的方法调用,一步步的过程来保证完成学习任务。

序列模型

序列模型实现在keras.models模块内,模块提供了模型的保存和重新加载的功能,方便我们可以中断和重新开始一个训练过程。

save_model(model,path)
load_model(path)

Sequential类

  • add(layer) 向链尾追加一层神经网络层
  • pop() 删除尾部的神经网络层
  • compile(optimizer,loss,metrics) 配置模型的训练参数
    • optimizer 选择使用的优化方法,提供下列可选项
      • SGD(Stochastic gradient descent) 随机梯度下降
      • RMSprop,RNN的好选择
      • Adagrad
      • Adadelta 文献
      • Adam 文献
      • Nadam 文献
      • TFOptimizer
    • loss 选择损失函数,提供下列可选项
      • mean_squared_error mse
      • mean_absolute_error mae
      • binary_crossentropy 二分类问题交叉熵
      • categorical_crossentropy 多分类交叉熵,y需要转为one_hot形式
      • cosine_proximity 余弦距离平均值的相反数
      • poisson (predictions - targets * log(predictions))的均值
    • metrics 选择计算结果
      • accuracy
      • binary_accuracy
      • categorical_accuracy
      • top_k_categorical_accracy
  • fit(x,y,batch_size,epochs) 使用数据对模型进行epochs轮的训练
  • evaluate(x,y,batch_size) 对模型在测试数据集上进行评估
  • predict/predict_class/predict_probe(x,batch_size,verbose=0) 使用模型对数据进行预测
  • train_on_batch/test_on_batch/predict_on_batch 系列方法均在一批数据上进行训练,测试与预测
  • fit_generator/evaluate_generator/predict_generator 系列方法均使用数据生成器产生的数据进行训练,测试与预测
  • get/set_weights()
  • save/load_weights(path) 模型训练参数的保存与加载

示例:mnist数据集训练

在例子中,mnist数据集使用tensor自带的dataset。其中数据分两部分,其中训练集60000条,测试集10000条。训练集中图像部分由(60000,28*28)的矩阵表示,矩阵的每个元素表示图像每个像素点的黑白取值,标签部分由(60000,1)矩阵表示,每行数字表示对应图像识别出的数字。关于mnist数据集的详细说明见此链接:http://yann.lecun.com/exdb/mnist/

这是官方文档给出的导入代码,但我同很多人有一样的问题,运行程序的时候发现并没有讲MNIST数据集导入,so,在网上找了很多资料,最后找到了解决方法。 先在你正在写的项目下创建文件夹MNIST_data Yann LeCun’s website。从官网下载四个压缩包,不用解压直接放入文件夹中 成功导入数据集,否则会报错,连接错误。

# coding=utf-8
import keras
from keras.models import Sequential
from keras.layers import Dense

from tensorflow.examples.tutorials.mnist import input_data

from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
# from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
# mnist =  read_data_sets(one_hot=True)
mnist = read_data_sets("MNIST_data/", one_hot=True)
img_train,label_train = mnist.train.next_batch(60000)
img_test,label_test   = mnist.test.next_batch(10000)

#构建模型
model = Sequential()
model.add(Dense(512,activation='relu',input_dim=784))
model.add(Dense(512,activation='relu'))
model.add(Dense(10,activation='softmax'))
model.compile(optimizer='Adagrad',loss='categorical_crossentropy',metrics=['accuracy'])

#训练及评估模型
hist = model.fit(img_train,label_train)
loss,accu = model.evaluate(img_test,label_test)
print("loss is %f accu is %f"%(loss,accu))

运行结果:

 32/10000 [..............................] - ETA: 12s
  576/10000 [>.............................] - ETA: 1s 
 1152/10000 [==>...........................] - ETA: 1s
 1728/10000 [====>.........................] - ETA: 0s
 2336/10000 [======>.......................] - ETA: 0s
 3008/10000 [========>.....................] - ETA: 0s
 3680/10000 [==========>...................] - ETA: 0s
 4352/10000 [============>.................] - ETA: 0s
 5056/10000 [==============>...............] - ETA: 0s
 5760/10000 [================>.............] - ETA: 0s
 6432/10000 [==================>...........] - ETA: 0s
 7072/10000 [====================>.........] - ETA: 0s
 7776/10000 [======================>.......] - ETA: 0s
 8288/10000 [=======================>......] - ETA: 0s
 8992/10000 [=========================>....] - ETA: 0s
 9664/10000 [===========================>..] - ETA: 0s
10000/10000 [==============================] - 1s 84us/step
loss is 0.079320 accu is 0.975500

函数模型

在了解了序列模型的基础上,只需要再理解到,在keras中,模型是可调用的,就可以使用函数模型了。参考下面的代码,和上面是等效的。

import keras
from keras.layers import Dense,Input
from keras.models import Model
from tensorflow.examples.tutorials.mnist import input_data

mnist =  input_data.read_data_sets("MNIST_data/",one_hot=True)

img_train,label_train = mnist.train.next_batch(60000)
img_test,label_test   = mnist.test.next_batch(10000)

input = Input(shape=(784,))
layer1 = Dense(512,activation='relu')(input)
layer2 = Dense(512,activation='relu')(layer1)
pred = Dense(10,activation='softmax')(layer2)

model = Model(inputs=input,outputs=pred)
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])

hist = model.fit(img_train,label_train,epochs=1)
loss,accu = model.evaluate(img_test,label_test)
print("loss is %f accu is %f"%(loss,accu))

运行结果

 32/10000 [..............................] - ETA: 9s
  672/10000 [=>............................] - ETA: 1s
 1248/10000 [==>...........................] - ETA: 0s
 1696/10000 [====>.........................] - ETA: 0s
 2336/10000 [======>.......................] - ETA: 0s
 2976/10000 [=======>......................] - ETA: 0s
 3584/10000 [=========>....................] - ETA: 0s
 4192/10000 [===========>..................] - ETA: 0s
 4800/10000 [=============>................] - ETA: 0s
 5440/10000 [===============>..............] - ETA: 0s
 5984/10000 [================>.............] - ETA: 0s
 6592/10000 [==================>...........] - ETA: 0s
 7200/10000 [====================>.........] - ETA: 0s
 7808/10000 [======================>.......] - ETA: 0s
 8448/10000 [========================>.....] - ETA: 0s
 9024/10000 [==========================>...] - ETA: 0s
 9632/10000 [===========================>..] - ETA: 0s
10000/10000 [==============================] - 1s 89us/step
loss is 0.146895 accu is 0.960400

第四部分

1 Callbacks

Callbacks提供了一系列的类,用于在训练过程中被回调,从而实现对训练过程进行观察和干涉。除了库提供的一些类,用户也可以自定义类。下面列举比较有用的回调类。

类名

作用

构造函数

ModelCheckpoint

用于在epoch间保存要模型

ModelCheckpoint(filepath, monitor=’val_loss’, save_best_only=False, save_weights_only=False, mode=’auto’, period=1)

EarlyStopping

当early stop被激活(如发现loss相比上一个epoch训练没有下降),则经过patience个epoch后停止训练。

EarlyStopping(monitor=’val_loss’, patience=0, mode=’auto’)

TensorBoard

生成tb需要的日志

TensorBoard(log_dir=’./logs’, histogram_freq=0, write_graph=True, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)

ReduceLROnPlateau

当指标变化小时,减少学习率

ReduceLROnPlateau(monitor=’val_loss’, factor=0.1, patience=10, mode=’auto’, epsilon=0.0001, cooldown=0, min_lr=0)

示例:

from keras.callbacks import ModelCheckpoint

model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

checkpointer = ModelCheckpoint(filepath="/tmp/weights.h5", save_best_only=True)
tensbrd = TensorBoard(logdir='path/of/log')
model.fit(X_train, Y_train, batch_size=128, callbacks=[checkpointer,tensbrd])

PS:加入tensorboard回调类后,就可以使用tensorflow的tensorboard命令行来打开可视化web服务了。

2 Application

本模块提供了基于image-net预训练好的图像模型,方便我们进行迁移学习使用。初次使用时,模型权重数据会下载到~/.keras/models目录下。

图像模型

说明

构造函数

InceptionV3

InceptionV3(include_top=True, weights=’imagenet’,input_tensor=None,input_shape=None,pooling=None,classes=1000)

ResNet50

ResNet50(include_top=True, weights=’imagenet’,input_tensor=None,input_shape=None,pooling=None,classes=1000)

VGG19

VGG19(include_top=True, weights=’imagenet’,input_tensor=None,input_shape=None,pooling=None,classes=1000)

VGG16

VGG16(include_top=True, weights=’imagenet’,input_tensor=None,input_shape=None,pooling=None,classes=1000)

Xception

Xception(include_top=True, weights=’imagenet’,input_tensor=None,input_shape=None,pooling=None, classes=1000)

参数说明

参数

说明

include_top

是否保留顶层的全连接网络, False为只要bottleneck

weights

‘imagenet’代表加载预训练权重, None代表随机初始化

input_tensor

可填入Keras tensor作为模型的图像输出tensor

input_shape

长为3的tuple,指明输入图片的shape,图片的宽高必须大于197

pooling

特征提取网络的池化方式。None代表不池化,最后一个卷积层的输出为4D张量。‘avg’代表全局平均池化,‘max’代表全局最大值池化

classes

图片分类的类别数,当include_top=True weight=None时可用

关于迁移学习,可以参考这篇文章:如何在极小数据集上实现图像分类。里面介绍了通过图像变换以及使用已有模型并fine-tune新分类器的过程。

3 模型可视化

utils包中提供了plot_model函数,用来将一个model以图像的形式展现出来。此功能依赖pydot-ng与graphviz。 pip install pydot-ng graphviz

from keras.utils import plot_model
model = keras.applications.InceptionV3()
plot_model(model, to_file='model.png')

第五部分 cnn实现cifar10图像分类模型

用CNN实现cifar10图像分类模型


1 卷积神经网络简介

卷积神经网络和全连接神经网络一样,都是由多个神经网络层连接而成。不同的是CNN一般是由多个卷积层,池化层交替连接起来,用于提取输入数据的高层特征,并缩小数据的维度。最后对提取出的特征进行神经网络分类形成最终的输出。更详细的卷积神经网络相关知识可参见第4节提供的链接。

2 Keras对CNN的支持

keras.layers包中实现了与CNN相关的层模型,分别实现在convolutional和pooling模块中。

2.1 convolutional模块

convolutional模块中实现了卷积层的层模型,用于数据的特征提取。

层名

作用

原型

Conv1D

1维卷积层

Conv1D(filters, kernel_size, strides=1, padding=’valid’)

Conv2D

2维卷积层

Conv2D(filters, kernel_size, strides=(1, 1), padding=’valid’,dilation_rate=(1, 1))

UpSampling1D

1维上采样,将数据重复指定的次数

UpSampling2D(size=2)

UpSampling2D

2维上采样,将数据在2个维度上重复指定的次数

UpSampling2D(size=(2, 2))

ZeroPadding2D

边界填充0

ZeroPadding2D(padding=(1, 1))

2D参数说明:

参数

说明

filters

卷积核的数目,也是处理后输出的深度

kernel_size

过滤器的窗口大小

strides

过滤器卷积的步长

padding

补0策略,valid/same

activation

激活函数

dilation_rate

指定dilated convolution中的膨胀比例

2.2 pooling模块

pooling模块中实现池化层的的最大池化与平均池化的层模型,用于数据维度的缩减。

层名

作用

原型

MaxPooling1D

对1维输入进行最大值池化过滤

MaxPooling1D(pool_size=2, strides=None, padding=’valid’)

AveragePooling1D

对1维输入进行平均池化过滤

AveragePooling1D(pool_size=2, strides=None, padding=’valid’)

MaxPooling2D

对2维输入进行最大值池化过滤

MaxPooling2D(pool_size=(2, 2), strides=None, padding=’valid’, data_format=None)

AveragePooling2D

对3维输入进行平均池化过滤

AveragePooling2D(pool_size=(2, 2), strides=None, padding=’valid’, data_format=None)

GlobalMaxPooling1D

对1维输入进行全局最大值池化过滤

GlobalMaxPooling1D()

GlobalAveragePooling1D

对1维输入进行全局平均值池化过滤

GlobalAveragePooling1D()

GlobalMaxPooling2D

对2维输入进行全局最大值池化过滤

GlobalMaxPooling2D()

GlobalAveragePooling2D

对2维输入进行全局平均值池化过滤

GlobalAveragePooling2D()

2D参数说明

参数

说明

pool_size

过滤器的大小,通常取(2,2)或(3,3)

strides

过滤器的移动步长,取2使得输出shape缩小一半

padding

valid为1填充,same为0填充

data_format

字符串,channels_first或channels_last之一

cifar10分类代码

下面的代码实现了一个下面结构的CNN模型,其结构为:卷积层->池化层->卷积层->池化层->全连结层->全连结层->Softmax层。

import keras
from keras.datasets import cifar10
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D

num_classes = 10
model_name = 'cifar10.h5'

# The data, shuffled and split between train and test sets:
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

x_train = x_train.astype('float32')/255
x_test = x_test.astype('float32')/255

# Convert class vectors to binary class matrices.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()

model.add(Conv2D(32, (3, 3), padding='same', input_shape=x_train.shape[1:]))
model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(num_classes))
model.add(Activation('softmax'))

model.summary()

# initiate RMSprop optimizer
opt = keras.optimizers.rmsprop(lr=0.001, decay=1e-6)

# train the model using RMSprop
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

hist = model.fit(x_train, y_train, epochs=1, shuffle=True)
model.save(model_name)

# evaluate
loss, accuracy = model.evaluate(x_test, y_test)
print (loss, accuracy)

运行结果

9664/10000 [===========================>..] - ETA: 0s
 9728/10000 [============================>.] - ETA: 0s
 9792/10000 [============================>.] - ETA: 0s
 9856/10000 [============================>.] - ETA: 0s
 9920/10000 [============================>.] - ETA: 0s
 9984/10000 [============================>.] - ETA: 0s
10000/10000 [==============================] - 9s 853us/step
1.252797156715393 0.5627

4 CNN学习资料

  1. 深入浅出Tensorflow之四:卷积神经网络
  2. CNN浅析和历年ImageNet冠军模型解析
  3. 深度学习利器:TensorFlow与深度卷积神经网络

第六部分 舆情分析 正负向

1 RNN简介

RNN即循环神经网络,其主要用途是处理和预测序列数据。在CNN中,神经网络层间采用全连接的方式连接,但层内节点之间却无连接。RNN为了处理序列数据,层内节点的输出还会重新输入本层,以实现学习历史,预测未来。 RNN的两个主要改进是LSTM(长短时记忆网络)GRU(门控循环单元),二者为基本神经单元增加了额外的功能门,从而更好的实现长时记忆的处理。 在此基础上,通过两层或者多个RNN层的堆叠,可以实现双向循环神经网络(bidirectionalRNN)及深层循环神经网络(deepRNN)。

2 Keras对RNN的支持

Keras在layers包的recurrent模块中实现了RNN相关层模型的支持,并在wrapper模块中实现双向RNN的包装器。

2.1 recurrent模块导出类

名称

作用

原型参数

SimpleRNN

全连接RNN网络

SimpleRNN(units, activation=’tanh’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’,dropout=0.0, recurrent_dropout=0.0))

GRU

门限循环单元层

GRU(units, activation=’tanh’, recurrent_activation=’hard_sigmoid’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’, dropout=0.0, recurrent_dropout=0.0)

LSTM

长短期记忆模型层

LSTM(units, activation=’tanh’, recurrent_activation=’hard_sigmoid’, use_bias=True, kernel_initializer=’glorot_uniform’, recurrent_initializer=’orthogonal’, bias_initializer=’zeros’, unit_forget_bias=True, dropout=0.0, recurrent_dropout=0.0)

2.2 wrapper模块导出类

名称

作用

原型参数

TimeDistributed

TimeDistributed(layer)

Bidirectional

双向RNN包装器

Bidirectional(layer, merge_mode=’concat’, weights=None)

model = Sequential()
model.add(Bidirectional(LSTM(10, return_sequences=True), input_shape=(5, 10)))
model.add(Bidirectional(LSTM(10)))
model.add(Dense(5))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

2.3 参数说明

名称

作用

units

RNN的单元数,也是输出维度

activation

激活函数,为预定义的激活函数名

dropout

0~1之间的浮点数,控制输入线性变换的神经元断开比例

recurrent_dropout

0~1之间的浮点数,控制循环状态的线性变换的神经元断开比例

return_sequences

True返回整个序列,用于stack两个层,False返回输出序列的最后一个输出

go_backwards

True,逆向处理输入序列并返回逆序后的序列

stateful

True,则一个batch中下标为i的样本的最终状态将会用作下一个batch同样下标的样本的初始状态

implementation

0为大的矩阵乘法,便于CPU加速。1为小矩阵乘法 便于GPU加速。2 LSTM和GRU有效,优化GPU运行

input_dim

当使用该层为模型首层时,应指定该值

input_length

当输入序列的长度固定时,该参数为输入序列的长度。当需要在该层后连接Flatten层,然后又要连接Dense层时,需要指定该参数

merge_mode

前向和后向RNN输出的结合方式,为sum,mul,concat,ave和None之一,若为None,则不结合,以列表形式返回

3 情感分析示例

下面的示例使用了LSTM模型,通过对豆瓣电视剧评论进行训练,最终使得模型可以对评论的好恶进行预测,或者说简单的情感分析。

3.1 语料处理

原始语料来自豆瓣,采集了约100w条豆瓣国产剧评论及对应的评分。在语料处理中,借助jeiba分词工具进行分词,并去除停词。这里下载停词表。最终处理得到的语料类似于下面的格式,即每行一条评论。每行第一个字段为评分,其余字段为分词去停词后的评论。 将语料文件review.csv放在corpus目录下。将stop_word.txt放在dict目录下

5  经典作品 道听途说 以为 懂 实际 读 觉得 独特 意想不到 新颖                  
5  东京 看过 热海 看过 回家                  
5  这部 电影 里 看出 东西 太多 比方说 注意 尾道 家中 鸡冠花 会 明白 黑白 影像 彩色 影像 不能 取代 魅力 母亲 热海 防波堤 上 说 东京 游览 热海 回家 真是 人生 非常 隽永 总结                  
5  刚 几幕 觉得 极 做作 哪有 众人 说 这般 好 再 耐心 看 下去 方 发觉 表面 客套 微笑 下 内心深处 悲凉 其实 很 幸福 其实 幸福 等到 老时 会 老伴 相视而笑
5  生活 总是 人 失望                  

3.2 评分与情感的关系

为了简化示例,简单的认为1-2分为负面情感,4-5分为正面情感。未评分及3分为中性,不计入训练。这样将问题转化为一个二分类问题。

3.3 文本向量表示

借助Keras提供的文本预处理类Tokenizer,可以很容易的实现文本向量化。处理代码如下:

texts = []
labels = []
for line in lines:
    fields = line.split()
    rate = int(fields[0])
    if rate==0 or rate==3:
        continue
    elif rate < 3:
        rate = 0
    else:
        rate = 1
    cont = fields[1:]
    cont = " ".join(cont)
    texts.append(cont)
    labels.append(rate)
tokenizer.fit_on_texts(texts)
tokenizer.texts_to_sequence(texts)

由于每句长度不同,为便于计算,最终统一用0填充成长度为100的向量.

3.4 模型构建

采用双向LSTM的结构,构建代码如下:

model = Sequential()
model.add(Embedding(vocab_size, 256, input_length=sentence_max_len))
model.add(Bidirectional(LSTM(128,implementation=2)))
model.add(Dropout(0.5))
model.add(Dense(2, activation='relu'))
model.compile('RMSprop', 'categorical_crossentropy', metrics=['accuracy'])

3.5 完整代码

from keras.models import Sequential
from keras.preprocessing.text import Tokenizer
import keras.preprocessing.sequence as S
from keras.utils import to_categorical
from keras.layers import Embedding, Bidirectional, LSTM, Dropout, Dense

import jieba
import json
import numpy as np

vocab_size = 350000
sentence_max_len = 100
model_path = 'keras.h5'

class SentimentLSTM:
    def __init__(self):
        self.tokenizer = Tokenizer(num_words=vocab_size)
        self.stop_words = []
        self.model = None

    def load_stop_word(self,path='dict/stop_word.txt'):
        with open(path, 'r') as f:
            for line in f:
                content = line.strip()
                self.stop_words.append(content.decode('utf-8'))

    def jieba_cut(self,line):
        lcut = jieba.lcut(line)
        cut = [x for x in lcut if x not in self.stop_words]
        cut = " ".join(cut)
        return cut

    def load_cuted_corpus(self, dir, input):
        f = open(dir + '/' + input , 'r')
        lines = f.readlines()
        texts = []
        labels = []
        for line in lines:
            fields = line.split()
            rate = int(fields[0])
            if rate==0 or rate==3:
                continue
            elif rate < 3:
                rate = 0
            else:
                rate = 1
            cont = fields[1:]
            cont = " ".join(cont)
            texts.append(cont)
            labels.append(rate)

        self.tokenizer.fit_on_texts(texts)
        f.close()
        return texts,labels

    def load_data(self):
        x,y = self.load_cuted_corpus('corpus', 'review.csv')
        x = self.tokenizer.texts_to_sequences(x)
        x = S.pad_sequences(x,maxlen=sentence_max_len)
        y = to_categorical(y,num_classes=2)
        return ((x[0:500000],y[0:500000]), (x[500000:], y[500000:]))

    def train(self,epochs=50):
        print ('building model ...')
        self.model = SentimentLSTM.build_model()

        print ('loading data ...')
        (text_train, rate_train), (text_test, rate_text) = self.load_data()

        print ('training model ...')
        self.model.fit(text_train, rate_train,batch_size=1000,epochs=epochs)
        self.model.save('model/keras.model')
        score = self.model.evaluate(text_test,rate_text)
        print (score)

    def load_trained_model(self,path):
        model = SentimentLSTM.build_model()
        model.load_weights(path)
        return model

    def predict_text(self,text):
        if self.model == None:
            self.model = self.load_trained_model(model_path)
            self.load_stop_word()
            self.load_cuted_corpus('corpus', 'review.csv')

        vect = self.jieba_cut(text)
        vect = vect.encode('utf-8')
        vect = self.tokenizer.texts_to_sequences([vect,])
        print (vect)
        return self.model.predict_classes(S.pad_sequences(np.array(vect),100))

    @staticmethod
    def build_model():
        model = Sequential()
        model.add(Embedding(vocab_size, 256, input_length=sentence_max_len))
        model.add(Bidirectional(LSTM(128,implementation=2)))
        model.add(Dropout(0.5))
        model.add(Dense(2, activation='relu'))
        model.compile('RMSprop', 'categorical_crossentropy', metrics=['accuracy'])
        return model

def main():
    lstm = SentimentLSTM()
    lstm.train(10)
    while True:
        input = input('Please input text:')
        if input == 'quit':
            break
        print (lstm.predict_text(input))

if __name__=="__main__":
    main()

运行代码,在训练完模型之后,在交互器中输入新的评论,即可以查看训练的模型对评论的预测了.负向输出为0,正向输出为1.

PS:在约60w的数据集上,CPU上跑10轮至少要10个小时.在GeForce GTX 1080上跑需要30分钟. 模型在测试集上的准确度能达到86%,召回率98%,精确度61%,F1评分75%.增大训练的轮数,100轮左右,仍可提升相关得分.

4 学习资料

1 深入浅出Tensorflow(五):循环神经网络简介

2 LSTM与GRU

第七部分 LSTM序列到序列模型种类

LSTM序列到序列模型种类 LSTM 序列到序列(seq to seq)问题建模, 根据问题和数据本身的特点,可以分为几种不同: - 一对一(one to one) - 多对一(many to one) - 一对多(one to many) - 多对多(many to many) 具体可以参考https://blog.csdn.net/happyhorizion/article/details/78636668

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券