NLP AI 自然語言處理 機器學習 Machine Learning

簡單快速上手自然語言處理中的文本分類

吳奇恩 Tony Wu 2020/08/24 17:35:21
715

本文為用Python3快速實作簡單文本分類之教學

開始前請先使用pip安裝Python3環境以及scikitlearn套件,本文使用 scikit-learn 版本 0.19.1,pandas版本1.0.5

使用其他版本的套件可能會有些許出入

指令如下

pip install scikit-learn==0.21.3
pip install pandas==1.0.5

或是

pip3 install scikit-learn==0.21.3
pip3 install pandas==1.0.5

 

Qick Start

請先至以下連結下載寫好的Excel語料

附件--昕力大學-文本分類.xlsx

 

並使用Python pandas套件讀取檔案

import pandas as pd
read = pd.read_excel("昕力大學-文本分類.xlsx", index=False).values.tolist()
corpus = [row[0] for row in read]
intents = [row[1] for row in read]

讀取完後可以將語料印出來後看看是否成功

corpus[:15]

向量化

接下來我們載入scikit-learn的Counter Vectorizer,將語句轉換成n元語法(N-gram)向量。

這裡設定的N-gram range 是 1-2,也就是說假設某一個句子"ABCDE",在做feature transform時,會把該句子轉成 "A","B","C","D","E","AB","BC","CD","DE",的形式當成feature。n元語法設定成1到2的方式又被稱為二元語法(Bigram)

詳細Counter Vectorizer使用方法,可以參考這裡

from sklearn.feature_extraction.text import CountVectorizer
feature_extractor = CountVectorizer(
            analyzer="word", ngram_range=(1, 2), binary=True,
            token_pattern=r'([a-zA-Z]+|\w)')
X = feature_extractor.fit_transform(corpus)

轉成二元語法(Bigram)向量後,我們可以看看總共得到多少數量的特徵,總共有605個這麼多

len(feature_extractor.get_feature_names())

試著將得到的特徵前三十筆印出來看看

feature_extractor.get_feature_names()[:30]

 

分類

接著我們將剛剛轉成二元語法形式的向量,也就是變數X,和在Excel當中讀取到每個句子所屬於的意圖(Intent),分別當成特徵和標籤送進邏輯回歸(Logistic Regrassion)裡去訓練。

from sklearn.linear_model import LogisticRegression
INTENT_CLASSIFY_REGULARIZATION = "l2"

lr = LogisticRegression(penalty=INTENT_CLASSIFY_REGULARIZATION,
                                         class_weight='balanced')
lr.fit(X, intents)

 

邏輯回歸的詳細概念可以自行Google。舉個例子,假設你有一群老鼠的身高體重,分別把他們標示成「正常」和「肥胖」

那麼把每個老鼠的數值用個兩個維度的向量(身高, 體重)來表示,也就是把身高放在二維坐標中的X軸,體重放在二維座標的Y軸,在座標平面上就會如下圖所示

邏輯回歸的目標就是找到一條線,這條線通常被稱作超平面(hyperplane),使得肥胖的老鼠和正常體重的老鼠在向量空間中能區隔開來

在得到這條線後,以後有新資料出現,例如一隻超極巨化的皮卡丘,就可以知道牠是屬於肥胖那個區域

 

預測

在訓練好邏輯回歸得模型後,我們就可以來預測新輸入的句子

例如一句新的句子「查詢明天的降雨量」,這是訓練資料集裡面所沒有的資料,我們來看看訓練好的邏輯回歸模型是否能順利把它歸類為「天氣」,首先我們先把該句子轉換為二元語法(Bigram)向量。

user_input = ['查詢明天的降雨量']
X2 = feature_extractor.transform(user_input)

可以看到轉成向量後的句子就如剛剛所說的,維度也是605

len(X2.toarray()[0])

將得到的測試用的X2向量印出來看看

這裡可以看到從使用者句子中抽取出來的Feature,以index方式呈現,代表該向量在第171, 179, 292, 293....的值為1,其他為0

print(X2)

用得到的index去查找,看看實際上抽取到的feature有哪些。可以看到「查詢明天的降雨量」這句話被抽到Bigram為「天、天的、明、明天、查、查詢、的、詢、詢明、雨」

feature_names = feature_extractor.get_feature_names()
for index in X2.nonzero()[1]:
    print(feature_names[index])

預測很簡單,我們用一行程式碼,就可以讓剛訓練好的邏輯回歸模型判斷該句子是屬於哪個類別(意圖)

lr.predict(X2)

想知道該句屬於每個意圖的機率,可以這樣做

probs = lr.predict_proba(X2)[0]
for predict_intent, prob in sorted(zip(lr.classes_, probs), key = lambda x: x[1],reverse = True):
    print(predict_intent, prob)

 

是不是覺得AI裡面的分類(Classfication)問題,就是如此的簡單呢?

大家可以自行編寫Excel表格裡的語句和意圖,就能建構屬於自己的AI文本分類器喔!

 

 

 

吳奇恩 Tony Wu