基于Python的豆瓣中文影评差评分析
資源下載地址:https://download.csdn.net/download/sheziqiong/86773473
資源下載地址:https://download.csdn.net/download/sheziqiong/86773473
1. NLP
NLP(Natural Language Processing)是指自然語言處理,他的目的是讓計算機可以聽懂人話。
下面是我將2萬條豆瓣影評訓(xùn)練之后,隨意輸入一段新影評交給神經(jīng)網(wǎng)絡(luò),最終AI推斷出的結(jié)果。
"很好,演技不錯", 0.91799414 ===>好評"要是好就奇怪了", 0.19483969 ===>差評"一星給字幕", 0.0028086603 ===>差評"演技好,演技好,很差", 0.17192301 ===>差評"演技好,演技好,演技好,演技好,很差" 0.8373259 ===>好評看完本篇文章,即可獲得上述技能。
2. 讀取數(shù)據(jù)
首先我們要找到待訓(xùn)練的數(shù)據(jù)集,我這里是一個csv文件,里面有從豆瓣上獲取的影視評論50000條。
他的格式是如下這樣的:
| 電影名 | 1分到5分 | 評論內(nèi)容 | 1 好評,0 差評 |
部分?jǐn)?shù)據(jù)是這樣的:
代碼是這樣的:
# 導(dǎo)入包 import csv import jieba# 讀取csv文件 csv_reader = csv.reader(open("datasets/douban_comments.csv"))# 存儲句子和標(biāo)簽 sentences = [] labels = []# 循環(huán)讀出每一行進行處理 i = 1 for row in csv_reader:# 評論內(nèi)容用結(jié)巴分詞以空格分詞comments = jieba.cut(row[2]) comment = " ".join(comments)sentences.append(comment)# 存入標(biāo)簽,1好評,0差評labels.append(int(row[3]))i = i + 1if i > 20000: break # 先取前2萬條試驗,取全部就注釋# 取出訓(xùn)練數(shù)據(jù)條數(shù),分隔開測試數(shù)據(jù)條數(shù) training_size = 16000 # 0到16000是訓(xùn)練數(shù)據(jù) training_sentences = sentences[0:training_size] training_labels = labels[0:training_size] # 16000以后是測試數(shù)據(jù) testing_sentences = sentences[training_size:] testing_labels = labels[training_size:]這里面做了幾項工作:
2.1 中文分詞
重點說一下分詞。
分詞是中文特有的,英文不存在。
下面是一個英文句子。
This is an English sentence.
請問這個句子,有幾個詞?
有6個,因為每個詞之間有空格,計算機可以輕易識別處理。
| 1 | 2 | 3 | 4 | 5 | 6 |
下面是一個中文句子。
歡迎訪問我的掘金博客。
請問這個句子,有幾個詞?
恐怕你得讀幾遍,然后結(jié)合生活閱歷,才能分出來,而且還帶著各類糾結(jié)。
今天研究的重點不是分詞,所以我們一筆帶過,采用第三方的結(jié)巴分詞實現(xiàn)。
安裝方法
代碼對 Python 2/3 均兼容
- 全自動安裝:easy_install jieba 或者 pip install jieba / pip3 install jieba
- 半自動安裝:先下載 http://pypi.python.org/pypi/jieba/ ,解壓后運行 python setup.py install
- 手動安裝:下載代碼文件將 jieba 目錄放置于當(dāng)前目錄或者 site-packages 目錄
- 通過 import jieba 來引用
引入之后,調(diào)用jieba.cut("歡迎訪問我的掘金博客。")就可以分詞了。
importjieba words=jieba.cut("歡迎訪問我的掘金博客。") sentence="".join(words) print(sentence)#歡迎訪問我的掘金博客。為什么要有分詞?因為詞語是語言的最小單位,理解了詞語才能理解語言,才知道說了啥。
對于中文來說,同一個的詞語在不同語境下,分詞方法不一樣。
關(guān)注下面的“北京大學(xué)”:
importjieba sentence="".join(jieba.cut("歡迎來北京大學(xué)餐廳")) print(sentence)#歡迎來北京大學(xué)餐廳 sentence2="".join(jieba.cut("歡迎來北京大學(xué)生志愿者中心")) print(sentence2)#歡迎來北京大學(xué)生志愿者中心所以,中文的自然語言處理難就難在分詞。
至此,我們的產(chǎn)物是如下格式:
sentences = ['我喜歡你','我不喜歡他',……] labels = [0,1,……]3. 文本序列化
文本,其實計算機是無法直接認(rèn)識文本的,它只認(rèn)識0和1。
你之所以能看到這些文字、圖片,是因為經(jīng)過了多次轉(zhuǎn)化。
就拿字母A來說,我們用65表示,轉(zhuǎn)為二進制是0100 0001。
| 0100 0001 | 65 | A | 大寫字母A |
| 0100 0010 | 66 | B | 大寫字母B |
| 0100 0011 | 67 | C | 大寫字母C |
| 0100 0100 | 68 | D | 大寫字母D |
| 0100 0101 | 69 | E | 大寫字母E |
當(dāng)你看到A、B、C時,其實到了計算機那里是0100 0001、0100 0010、0100 0011,它喜歡數(shù)字。
Tips:這就是為什么當(dāng)你比較字母大小是發(fā)現(xiàn) A<B ,其實本質(zhì)上是65<66。
那么,我們的準(zhǔn)備好的文本也需要轉(zhuǎn)換為數(shù)字,這樣更便于計算。
3.1 fit_on_texts 分類
有一個類叫Tokenizer,它是分詞器,用于給文本分類和序列化。
這里的分詞器和上面我們說的中文分詞不同,因為編程語言是老外發(fā)明的,人家不用特意分詞,他起名叫分詞器,就是給詞語分類。
fromtensorflow.keras.preprocessing.textimportTokenizersentences=['我喜歡你','我不喜歡他'] # 定義分詞器 tokenizer=Tokenizer() # 分詞器處理文本, tokenizer.fit_on_texts(sentences) print(tokenizer.word_index) # {'我':1,'喜歡':2,'你':3,'不':4,'他':5}上面做的就是找文本里有幾類詞語,并編上號。
看輸出結(jié)果知道:2句話最終抽出5種不同的詞語,編號1~5。
3.2 texts_to_sequences 文本變序列
文本里所有的詞語都有了編號,那么就可以用數(shù)字表示文本了。
# 文本轉(zhuǎn)化為數(shù)字序列 sequences=tokenizer.texts_to_sequences(sentences) print(sequences)#[[1,2,3],[1,4,2,5]]這樣,計算機漸漸露出了笑容。
3.3 pad_sequences 填充序列
雖然給它提供了數(shù)字,但這不是標(biāo)準(zhǔn)的,有長有短,計算機就是流水線,只吃統(tǒng)一標(biāo)準(zhǔn)的數(shù)據(jù)。
pad_sequences 會把序列處理成統(tǒng)一的長度,默認(rèn)選擇里面最長的一條,不夠的補0。
fromtensorflow.keras.preprocessing.sequenceimportpad_sequences# padding='post'后邊填充,padding='pre'前面填充 padded=pad_sequences(sequences,padding='post') print(padded)#[[1 2 3] [1 4 2 5]] -> [[1230][1425]]這樣,長度都是一樣了,計算機露出了開心的笑容。
少了可以補充,但是如果太長怎么辦呢?
太長可以裁剪。
# truncating='post'裁剪后邊,truncating='pre'裁剪前面 padded=pad_sequences(sequences,maxlen=3,truncating='pre') print(padded)#[[1,2,3],[1,4,2,5]]->[[123][425]]至此,我們的產(chǎn)物是這樣的格式:
sentences = [[1 2 3 0] [1 4 2 5]] labels = [0,1,……]4. 構(gòu)建模型
所謂模型,就是流水線設(shè)備。我們先來看一下流水線是什么感覺。
看完了吧,流水線的作用就是進來固定格式的原料,經(jīng)過一層一層的處理,最終出去固定格式的成品。
模型也是這樣,定義一層層的“設(shè)備”,配置好流程中的各項“指標(biāo)”,等待上線生產(chǎn)。
# 構(gòu)建模型,定義各個層 model=tf.keras.Sequential([ tf.keras.layers.Embedding(vocab_size,embedding_dim,input_length=max_length), tf.keras.layers.GlobalAveragePooling1D(), tf.keras.layers.Dense(64,activation='relu'), tf.keras.layers.Dense(1,activation='sigmoid') ]) # 配置訓(xùn)練方法loss=損失函數(shù)optimizer=優(yōu)化器metrics=["準(zhǔn)確率”] model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])4.1 Sequential 序列
你可以理解為整條流水線,里面包含各類設(shè)備(層)。
4.2 Embedding 嵌入層
嵌入層,從字面意思我們就可以感受到這個層的氣勢。
嵌入,就是插了很多個維度。一個詞語用多個維度來表示。
下面說維度。
二維的是這樣的(長,寬):
三維是這樣的(長,寬,高):
100維是什么樣的,你能想象出來嗎?除非物理學(xué)家,否則三維以上很難用空間來描述。但是,數(shù)據(jù)是很好體現(xiàn)的。
性別,職位,年齡,身高,膚色,這一下就是5維了,1000維是不是也能找到。
對于一個詞,也是可以嵌入很多維度的。有了維度上的數(shù)值,我們就可以理解詞語的輕重程度,可以計算詞語間的關(guān)系。
如果我們給顏色設(shè)置R、B、G 3個維度:
| 紅色 | 255 | 0 | 0 |
| 綠色 | 0 | 255 | 0 |
| 藍(lán)色 | 0 | 0 | 255 |
| 黃色 | 255 | 255 | 0 |
| 白色 | 255 | 255 | 255 |
| 黑色 | 0 | 0 | 0 |
下面見證一下奇跡,懂色彩學(xué)的都知道,紅色和綠色摻在一起是什么顏色?
來,跟我一起讀:紅色+綠色=黃色。
到數(shù)字上就是:[255,0,0]+[0,255,0] = [255,255,0]
這樣,顏色的明暗程度,顏色間的關(guān)系,計算機就可以通過計算得出了。
只要標(biāo)記的合理,其實計算機能夠算出:國王+女性=女王、精彩=-糟糕,開心>微笑。
那你說,計算機是不是理解詞語意思了,它不像你是感性理解,它全是數(shù)值計算。
嵌入層就是給詞語標(biāo)記合理的維度。
我們看一下嵌入層的定義:Embedding(vocab_size,embedding_dim,input_length)
- vocab_size:字典大小。有多少類詞語。
- embedding_dim:本層的輸出大小。一個詞用多少維表示。
- input_length:輸入數(shù)據(jù)的維數(shù)。一句話有多少個詞語,一般是max_length(訓(xùn)練集的最大長度)。
4.3 GlobalAveragePooling1D 全局平均池化為一維
主要就是降維。我們最終只要一維的一個結(jié)果,就是好評或者差評,但是現(xiàn)在維度太多,需要降維。
4.4 Dense
這個也是降維,Dense(64,activation='relu')降到Dense(1,activation='sigmoid'),最終輸出一個結(jié)果,就像前面流水線輸入面粉、水、肉、菜等多種原材料,最終出來的是包子。
4.5 activation 激活函數(shù)
activation是激活函數(shù),它的主要作用是提供網(wǎng)絡(luò)的非線性建模能力。
所謂線性問題就是可以用一條線能解決的問題。
可以來TensorFlow游樂場來試驗。
如果是采用線性的思維,神經(jīng)網(wǎng)絡(luò)很快就能區(qū)分開這兩種樣本。
但如果是下面的這種樣本,畫一條直線是解決不了的。
如果是用relu激活函數(shù),就可以很輕易區(qū)分。
這就是激活函數(shù)的作用。
常用的有如下幾個,下面有它的函數(shù)和圖形。
我們用到了relu和sigmoid。
- relu:線性整流函數(shù)(Rectified Linear Unit),最常用的激活函數(shù)。
- sigmoid:也叫Logistic函數(shù),它可以將一個實數(shù)映射到(0,1)的區(qū)間。
Dense(1,activation='sigmoid')最后一個Dense我們就采用了sigmoid,因為我們的數(shù)據(jù)集中0是差評,1是好評,我們期望模型的輸出結(jié)果數(shù)值也在0到1之間,這樣我們就可以判斷是更接近好評還是差評了。
4. 訓(xùn)練模型
4.1 fit 訓(xùn)練
訓(xùn)練模型就相當(dāng)于啟動了流水線機器,傳入訓(xùn)練數(shù)據(jù)和驗證數(shù)據(jù),調(diào)用fit方法就可以訓(xùn)練了。
啟動后,日志打印是這樣的:
Epoch 1/10 500/500 - 61s - loss: 0.6088 - accuracy: 0.6648 - val_loss: 0.5582 - val_accuracy: 0.7275 Epoch 2/10 500/500 - 60s - loss: 0.4156 - accuracy: 0.8130 - val_loss: 0.5656 - val_accuracy: 0.7222 Epoch 3/10 500/500 - 60s - loss: 0.2820 - accuracy: 0.8823 - val_loss: 0.6518 - val_accuracy: 0.7057經(jīng)過訓(xùn)練,神經(jīng)網(wǎng)絡(luò)會根據(jù)輸入和輸出自動調(diào)節(jié)參數(shù),包括確定詞語的具體維度,以及維度的數(shù)值取多少。這個過程變?yōu)楹诤辛?#xff0c;這也是人工智能和傳統(tǒng)程序設(shè)計不同的地方。
最后,調(diào)用save_weights可以把結(jié)果保存下來。
5. 自動分析結(jié)果
5.1 predict 預(yù)測
分詞處理
v_len = len(sentences)
for i in range(v_len):
sentences[i] = " ".join(jieba.cut(sentences[i]) )
序列化
sequences = tokenizer.texts_to_sequences(sentences)
填充為標(biāo)準(zhǔn)長度
padded = pad_sequences(sequences, maxlen= max_length, padding=‘post’, truncating=‘post’)
預(yù)測
predicts = model.predict(np.array(padded))
打印結(jié)果
for i in range(len(sentences)):
print(sentences[i], predicts[i][0],‘=>好評’ if predicts[i][0] > 0.5 else '=>差評’)
資源下載地址:https://download.csdn.net/download/sheziqiong/86773473
資源下載地址:https://download.csdn.net/download/sheziqiong/86773473
總結(jié)
以上是生活随笔為你收集整理的基于Python的豆瓣中文影评差评分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XP母盘制作详细教程(完全版)(转)
- 下一篇: 经典游戏IP:传统端游大厂的成功“捷径”