1. 程式人生 > 實用技巧 >基於機器學習的文字分類NLP基本介紹

基於機器學習的文字分類NLP基本介紹

學習目的:

1 學會TF-IDF的原理和使用
2 使用sklearn的機器學習模型完成文字分類

處理文字方法:

1 One-hot(獨熱編碼)
2 Bag of Words(詞袋)
3 N-gram
4 TF-IDF 分數

下面具體介紹每種方法

one-hot:即將每一個單詞使用一個離散的向量表示。具體將每個字/詞編碼一個索引,然後根據索引進行賦值

如:

句子1:我 愛 北 京 天 安 門
句子2:我 喜 歡 上 海

首先對所有句子的字進行索引,即將每個字確定一個編號: {
'': 1, '': 2, '': 3, '': 4, '': 5, '': 6, '': 7, '
': 8, '': 9, '': 10, '': 11}
得到有個11維的稀疏矩陣 我:[
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 愛:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] ... 海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

Bag of Words(詞袋錶示),也稱為Count Vectors,每個文件的字/詞可以使用其出現次數來進行表示

#直接統計每個字出現的次數,並進行賦值:
句子1:我 愛 北 京 天 安 門
轉換為 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]

句子2:我 喜 歡 上 海
轉換為 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]

在sklearn中可以直接CountVectorizer來實現這一步驟

from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()

N-gram與Count Vectors類似,不過加入了相鄰單詞組合成為新的單詞,並進行計數

如果N取值為2,則句子1和句子2就變為:

句子1:我愛 愛北 北京 京天 天安 安門
句子2:我喜 喜歡 歡上 上海

TF-IDF 分數由兩部分組成:

第一部分是詞語頻率(Term Frequency),第二部分是逆文件頻率(Inverse Document Frequency)。

其中計算語料庫中文件總數除以含有該詞語的文件數量,然後再取對數就是逆文件頻率

1 TF(t)= 該詞語在當前文件出現的次數 / 當前文件中詞語的總數
2 IDF(t)= log_e(文件總數 / 出現該詞語的文件總數)

程式碼實現

# Count Vectors + RidgeClassifier

import pandas as pd

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score

train_df = pd.read_csv('../data/train_set.csv', sep='\t', nrows=15000)

vectorizer = CountVectorizer(max_features=3000)
train_test = vectorizer.fit_transform(train_df['text'])

clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])

val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
# 0.74

# TF-IDF +  RidgeClassifier

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score

train_df = pd.read_csv('../data/train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])

val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
# 0.87