Press "Enter" to skip to content

深度学习框架Keras介绍及实战

Keras 是一个用 Python 编写的高级神经网络 API,它能够以
TensorFlow, CNTK, 或者 Theano 作为后端运行。Keras 的开发重点是支持快速的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。

 

本文以Kaggle上的项目:IMDB影评情感分析为例,学习如何用Keras搭建一个神经网络,处理实际问题.阅读本文需要对神经网络有基础的了解.

 

文章分为两个部分:

 

Keras中的一些基本概念.Api用法.我会给出一些简单的使用样例,或是给出相关知识链接.

 

IMDB影评情感分析实战.用到的都是第一部分中讲到的知识点.

 

Model

 

Dense 全连接层

 

 keras.layers.core.Dense(units, activation=None, use_bias=True, k
 ernel_initializer='glorot_uniform', bias_initializer='zeros', ke
 rnel_regularizer=None, bias_regularizer=None, activity_regulariz
 er=None, kernel_constraint=None, bias_constraint=None)

 

 # as first layer in a sequential model:
 # as first layer in a sequential model:
 model = Sequential()
 model.add(Dense(32, input_shape=(16,)))
 # now the model will take as input arrays of shape (*, 16)
 # and output arrays of shape (*, 32)
 # after the first layer, you don't need to specify
 # the size of the input anymore:
 model.add(Dense(32))

 

嵌入层 Embedding

 

 keras.layers.embeddings.Embedding (input_dim, output_dim, embeddi
 ngs_initializer='uniform', embeddings_regularizer=None, activity
 _regularizer=None, embeddings_constraint=None, mask_zero=False,
 input_length=None)

 

有兴趣的看这个 链接

 

其实就是word to vector。 这一层的作用就是得到用词向量表示的文本.

 

input_dim: 词表的大小.即不同的词的总个数.

 

output_dim:想要把词转换成多少维的向量.

 

input_length: 每一句的词的个数

 

比如如下代表:我们输入一个M*50的矩阵,这个矩阵中不同的词的个数为200,我们想把每个词转换为32维向量.
返回的是一个(M,50,32)的张量.

 

一个句子50个词,每个词是32维向量,共M个句子. 所以是e.shape=(M,50,32)

e = Embedding(200,
32, input_length=50)

LSTM层.

 

LSTM
是循环神经网络的一种特殊情况 .

 

简单来说,我们此前说过的神经网络,包括CNN,都是单向的,没有考虑序列关系,但是某个词的意义与其上下文是有关的,比如”我用着小米手机,吃着小米粥”,两个小米肯定不是一个意思.在做语义分析的时候,需要考虑上下文.
循环神经网络RNN就是干这个事情的.或者说”这部电影质量很高,但是我不喜欢”.这个句子里既有正面评价,又有负面评价,参考上下文的LSTM会识别出”但是”后面的才是我们想要重点表达的.

 

 keras.layers.recurrent.LSTM (units, activation='tanh', v recurrent_
 activation='hard_sigmoid', use_bias=True, kernel_initializer='gl
 orot_uniform', recurrent_initializer='orthogonal', bias_initiali
 zer='zeros', unit_forget_bias=True, kernel_regularizer=None, rec
 urrent_regularizer=None, bias_regularizer=None, activity_regular
 izer=None, kernel_constraint=None, recurrent_constraint=None, bi
 as_constraint=None, dropout=0.0, recurrent_dropout=0.0)

 

池化层

 

keras.layers.pooling.GlobalMaxPooling1D() #对时间信号的全局最大池化 https://stackoverflow.com/ questions/43728235/what-is -the-difference-between -keras-maxpooling1d-and- globalmaxpooling1d-functi>

 

input:形如( samples, steps, features) 的3D张量

 

output:形如(samples, features)的2D张量

 

keras.layers.pooling.MaxPooling1D (pool_size=2, strides=None,
pad

 

ding=’valid’)

 

keras.layers.pooling.MaxPooling2D (pool_size=(2, 2),
strides=None

 

, padding=’valid’, data_format=None)

 

keras.layers.pooling.MaxPooling3D (pool_size=(2, 2,
2), strides=N

 

one, padding=’valid’, data_format=None)

 

….

 

数据预处理

 

文本预处理

 

keras.preprocessing.text. text_to_word_sequence(text,

 

filters=base_filter(), lower=True, split=” “)

 

keras.preprocessing.text.one_hot (text, n,

 

filters=base_filter(), lower= True, split=” “)

 

keras.preprocessing.text.Tokenizer (num_words=None,
filters=base_

 

filter(),

 

lower=True, split=” “)

 

Tokenizer是一个用于向量化文本, 或将文本转换为序列( 即单词在字典中的下标构

 

成的列表, 从1算起) 的类。

 

num_words: None或整数, 处理的最大单词数量。 若被设置为整数, 则分词器

 

将被限制为处理数据集中最常见的 num_words 个单词

 

不管num_words是几,fit_on_texts以后词典都是一样的,全部的词都有对应的index.只是在做texts_to_sequences时所得结果不同.

 

会取最常出现的(num_words – 1)个词对应的index来代表句子.

 

注意num_words不同时,准换后X_t的不同. 只取词典中出现最多的num_words – 1代表句子.如果一个句子中出现特别生僻的词,就会被过滤掉.比如一个句子=”x
y z”.y,z不在词典中最常出现的top num_words-1的话,最后这个句子的向量形式则为[x_index_in_dic]

 

t1=”i love
that girl”

 

t2=’i hate u’

 

texts=[t1,t2]

 

tokenizer = Tokenizer(num_words=None)

 

tokenizer.fit_on_texts(texts) #得到词典 每个词对应一个index.

 

print( tokenizer.word_counts) #OrderedDict([(‘i’,
2), (‘love’, 1), (‘that’, 1), (‘girl’, 1), (‘hate’,
1), (‘u’, 1)])

 

print( tokenizer.word_index) #{‘i’: 1, ‘love’:
2, ‘that’: 3, ‘girl’: 4, ‘hate’: 5, ‘u’: 6}

 

print( tokenizer.word_docs) #{‘i’: 2, ‘love’:
1, ‘that’: 1, ‘girl’: 1, ‘u’: 1, ‘hate’: 1})

 

print( tokenizer.index_docs) #{1: 2, 2: 1, 3:
1, 4: 1, 6: 1, 5: 1}

 

tokennized_texts = tokenizer.texts_to_sequences(texts)

 

X_t = pad_sequences(tokennized_texts, maxlen=None)
#转换为2d array 即矩阵形式. 每个文本的词的个数均为maxlen. 不存在的词用0表示.

 

print(X_t)#[[1 2 3 4][0 1 5 6]]

 

序列预处理

 

keras.preprocessing.sequence.pad_sequences
(sequences, maxlen=None

 

, dtype=’int32′,

 

padding=’pre’, truncating=’pre’, value=0.)

 

返回一个2阶张量

 

keras.preprocessing.sequence.skipgrams
(sequence, vocabulary_size

 

,

 

window_size=4, negative_samples=1.,
shuffle=True,

 

categorical=False, sampling_table=None)

 

keras.preprocessing.sequence.make
_sampling_table (size, sampling_

 

factor=1e-5)

 

keras实战:IMDB影评情感分析

 

数据集介绍

 

labeledTrainData.tsv/imdb_master.csv 影评数据集 已经标注对电影是正面/负面评价

 

testData.tsv 测试集 需要预测评论是正面/负面

 

主要步骤

 

数据读取

 

数据清洗 主要包括去除停词,去除html tag,去除标点符号

 

模型构建

 

嵌入层:完成词到向量的转换

 

LSTM

 

池化层:完成重要特征抽取

 

全连接层:分类

 

数据加载

 

 import pandas as pd
 import matplotlib.pyplot as plt
 import numpy as np
 df_train = pd.read_csv("./dataset/word2vec-nlp-tutorial/labeledTrainData.tsv", header=0, delimiter="\t", quoting=3)
 df_train1=pd.read_csv("./dataset/imdb-review-dataset/imdb_master.csv",encoding="latin-1")
 df_train1=df_train1.drop(["type",'file'],axis=1)
 df_train1.rename(columns={'label':'sentiment',
 'Unnamed: 0':'id',
 'review':'review'}, 
 inplace=True)
 df_train1 = df_train1[df_train1.sentiment != 'unsup']
 df_train1['sentiment'] = df_train1['sentiment'].map({'pos': 1, 'neg': 0})
 new_train=pd.concat([df_train,df_train1])

 

数据清洗

 

用bs4处理html数据

 

过滤出单词

 

去除停用词

 

import re

 

from bs4 import BeautifulSoup

 

from nltk.corpus import stopwords

 

def review_to_words( raw_review ):

 

review_text = BeautifulSoup (raw_review, ‘lxml’).get_text()

 

letters_only = re.sub(“[^a-zA-Z]”, ”
“, review_text)

 

words = letters_only.lower().split()

 

stops = set (stopwords.words(“english”))

 

return( ” “.join ( meaningful_words
))

 

new_train[‘review’]= new_train[‘review’].apply(review_to_words)

 

df_test[“review”]= df_test[“review”].apply(review_to_words)

 

Keras搭建网络

 

文本转换为矩阵

 

– Tokenizer作用于list(sentence)得到词典.将词用词在词典中的Index做替换,得到数字矩阵

 

– pad_sequences做补0. 保证矩阵每一行数目相等.
即每个句子有相同数量的词.

 

list_classes
= [“sentiment”]

 

y = new_train[list_classes].values

 

print(y.shape)

 

list_sentences_train = new_train[“review”]

 

max_features = 6000

 

tokenizer = Tokenizer (num_words=max_features)

 

tokenizer.fit_on_texts (list(list_sentences_train))

 

list_tokenized_train = tokenizer.texts_to_sequences (list_sentences_train)

 

list_tokenized_test = tokenizer.texts_to_sequences (list_sentences_test)

 

print (len(tokenizer.word_index))

 

totalNumWords = [len(one_comment) for one_comment
in list_tokenized_train]

 

print(max(totalNumWords), sum(totalNumWords)
/ len(totalNumWords))

 

maxlen = 400

 

X_t = pad_sequences( list_tokenized_train, maxlen=maxlen)

 

X_te = pad_sequences (list_tokenized_test, maxlen=maxlen)

 

模型构建

 

词转向量

 

 inp = Input(shape=(maxlen, ))
 print(inp.shape) # (?, 400) #每个句子400个词
 embed_size = 128 #每个词转换成128维的向量
 x = Embedding(max_features, embed_size)(inp)
 print(x.shape) #(?, 400, 128)

 

LSTM 60个神经元

 

GlobalMaxPool1D 相当于抽取出最重要的神经元输出

 

DropOut 丢弃部分输出 引入正则化,防止过拟合

 

Dense 全连接层

 

模型编译时指定损失函数,优化器,模型效果评测标准

 

 x = LSTM(60, return_sequences=True,name='lstm_layer')(x)
 print(x.shape)
 x = GlobalMaxPool1D()(x)
 print(x.shape)
 x = Dropout(0.1)(x)
 print(x.shape)
 x = Dense(50, activation="relu")(x)
 print(x.shape)
 x = Dropout(0.1)(x)
 print(x.shape)
 x = Dense(1, activation="sigmoid")(x)
 print(x.shape)
 model = Model(inputs=inp, outputs=x)
 model.compile(loss='binary_crossentropy',
 optimizer='adam',
 metrics=['accuracy'])

 

模型训练

 

 batch_size = 32
 epochs = 2
 print(X_t.shape,y.shape)
 model.fit(X_t,y, batch_size=batch_size, epochs=epochs, validation_split=0.2)

 

使用模型预测

 

prediction =
model.predict(X_te)

 

y_pred = (prediction > 0.5)

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注