深度學習框架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)

有興趣的看這個鏈接https://machinelearningmastery.com/use-word-embedding-layers-deep-learning-keras/
其實就是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是循環神經網絡的一種特殊情況.http://deeplearning.net/tutorial/lstm.html
簡單來說,我們此前說過的神經網絡,包括CNN,都是單向的,沒有考慮序列關系,但是某個詞的意義與其上下文是有關的,比如"我用着小米手機,吃着小米粥",兩個小米肯定不是一個意思.在做語義分析的時候,需要考慮上下文. 循環神經網絡RNN就是干這個事情的.或者說"這部電影質量很高,但是我不喜歡".這個句子里既有正面評價,又有負面評價,參考上下文的LSTM會識別出"但是"后面的才是我們想要重點表達的.

keras.layers.recurrent.LSTM(units, activation='tanh', 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.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) 
print(tokennized_texts) #[[1, 2, 3, 4], [1, 5, 6]] 每個詞由其index表示

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"))                  
    meaningful_words = [w for w in words if not w in stops]   

    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"]
list_sentences_test = df_test["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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM