文本分类---逻辑回归(1)
基于sklearn的文本分類(lèi)—邏輯回歸(1)
本文是文本分類(lèi)的第一篇,記錄使用邏輯回歸進(jìn)行文本分類(lèi)任務(wù),數(shù)據(jù)集下載地址:http://thuctc.thunlp.org/
文本分類(lèi)的主要內(nèi)容如下:
-0 THUCNews數(shù)據(jù)集處理方法
- 1.基于邏輯回歸的文本分類(lèi)
- 2.基于樸素貝葉斯的文本分類(lèi)
- 3.使用LDA進(jìn)行文檔降維以及特征選擇
- 4.基于SVM的文本分類(lèi)
- 5.基于多層感知機(jī)MLPC的文本分類(lèi)
- 6.基于卷積神經(jīng)網(wǎng)絡(luò)詞級(jí)別的文本分類(lèi)以及調(diào)參
- 7.基于卷積神經(jīng)網(wǎng)絡(luò)的句子級(jí)別的文本分類(lèi)以及調(diào)參
- 8.基于Facebook fastText的快速高效文本分類(lèi)
- 9.基于RNN的文本分類(lèi)
- 10.基于LSTM的文本分類(lèi)
- 11.總結(jié)
1 數(shù)據(jù)預(yù)處理
其中使用的訓(xùn)練數(shù)據(jù)來(lái)自清華大學(xué)開(kāi)源的文本分類(lèi)數(shù)據(jù)集,原始數(shù)據(jù)集比較大,提供下載的是提取的小數(shù)據(jù),thu_data_500 表示每個(gè)類(lèi)提取500篇文章,thu_data_3000 表示每個(gè)類(lèi)提取3000篇文章,一共14個(gè)類(lèi)別,數(shù)據(jù)處理的代碼如下:
import os import codecs import jieba import refrom sklearn.utils import shuffle category = ['星座', '股票', '房產(chǎn)', '時(shí)尚', '體育', '社會(huì)', '家居', '游戲', '彩票', '科技', '教育', '時(shí)政', '娛樂(lè)', '財(cái)經(jīng)'] # 每篇文檔保留的文檔數(shù)量 #per_class_max_docs = 1000def load_data_to_mini(path, to_path, per_class_max_docs=1000):"""處理清華大學(xué)語(yǔ)料庫(kù),將類(lèi)別和文檔處理成fasttext 所需要的格式:param path: :param to_path: :return: """# 抽取后的語(yǔ)料庫(kù)corpus = []if not os.path.isdir(path):print('path error')# 列舉當(dāng)前目錄下的所有子列別目錄with codecs.open(to_path, 'w') as f:for files in os.listdir(path):curr_path = os.path.join(path, files)print(curr_path)if os.path.isdir(curr_path):count = 0docs = []for file in os.listdir(curr_path):count += 1if count > per_class_max_docs:breakfile_path = os.path.join(curr_path, file)# 讀取文件中的內(nèi)容with codecs.open(file_path, 'r', encoding='utf-8') as fd:docs.append('__label__' + files + ' ' + ' '.join(jieba.cut(re.sub('[ \n\r\t]+', '', fd.read()))))f.write('__label__' + files + ' ' + ' '.join(jieba.cut(re.sub('[ \n\r\t]+', '', fd.read()))))corpus.append(docs)# 將數(shù)據(jù)寫(xiě)到一個(gè)新的文件中with codecs.open(to_path, 'a') as f:for docs in corpus:for doc in docs:f.write(doc + '\n')return corpus通過(guò)調(diào)用下面的代碼,執(zhí)行小數(shù)據(jù)集的提取
corpus = load_data_to_mini('/root/git/data/THUCNews', 'thu_data_all', 3000) /root/git/data/THUCNews/娛樂(lè) /root/git/data/THUCNews/星座 /root/git/data/THUCNews/時(shí)尚 /root/git/data/THUCNews/股票 /root/git/data/THUCNews/彩票 /root/git/data/THUCNews/體育 /root/git/data/THUCNews/房產(chǎn) /root/git/data/THUCNews/社會(huì) /root/git/data/THUCNews/財(cái)經(jīng) /root/git/data/THUCNews/家居 /root/git/data/THUCNews/游戲 /root/git/data/THUCNews/科技 /root/git/data/THUCNews/教育 /root/git/data/THUCNews/時(shí)政我們看下提取的結(jié)果
print('corpus size(%d,%d)' %(len(corpus), len(corpus[0]))) corpus size(14,1000)可以看到,結(jié)果一共是14個(gè)類(lèi),每個(gè)類(lèi)500篇文檔,下面看下corpus里面的具體內(nèi)容
corpus[0][1] '__label__股票 世基 投資 : 緊縮 壓力 驟然 增加 滬 指 再失 2800 \u3000 \u3000 余煒 \u3000 \u3000 周二 大盤(pán) 在 半年線(xiàn) 處 止跌 后 , 連續(xù) 3 日 展開(kāi) 反彈 , 昨日 一度 站上 過(guò) 2830 點(diǎn) , 但 最終 還是 未能 收復(fù) , 顯示 出 20 日線(xiàn) 和 年線(xiàn) 從技術(shù)上 對(duì) 市場(chǎng) 的 壓力 比 想象 中 更加 大 。 弱勢(shì) 格局 下 , 利空 傳言 紛至沓來(lái) , 周末 效應(yīng) 再次 顯現(xiàn) , 周五 大盤(pán) 給 我們 呈現(xiàn)出 的 是 一幕 疲軟 下滑 走勢(shì) , 使得 前三天 的 反彈 基本 化為烏有 , 2800 點(diǎn) 再 一次 失守 , 股指 重新 來(lái)到 半年線(xiàn) 附近 求 支撐 。 \u3000 \u3000 盤(pán)面 熱點(diǎn) 比較 稀少 , 其中 資產(chǎn)重組 、 業(yè)績(jī) 增長(zhǎng) 和 預(yù)增 題材 的 幾只 品種 漲勢(shì) 不錯(cuò) , 昨日 提到 過(guò) 的 廣電 信息 、 銀鴿投資 連續(xù) 漲停 , 計(jì)劃 高送 轉(zhuǎn) 的 精誠(chéng) 銅業(yè) 也 受大單 推動(dòng) 漲停 。 此外 , 高鐵 概念 逆勢(shì) 重新 活躍 , 晉億 實(shí)業(yè) 最高 逼近 漲停 , 帶動(dòng) 晉西 車(chē)軸 、 中國(guó) 北車(chē) 、 天馬 股份 等 快速 上攻 , 其中 北車(chē) 和 晉 億 實(shí)業(yè) 已經(jīng) 率先 創(chuàng)出 階段 新高 。 部分 具備 病菌 概念 的 醫(yī)藥 股 也 表現(xiàn) 較 好 , 自早 盤(pán)起 就 展現(xiàn) 強(qiáng)勢(shì) , 萊茵 生物 漲停 , 紫鑫 藥業(yè) 、 海王 生物 、 聯(lián)環(huán) 藥業(yè) 大漲 7% 左右 。 \u3000 \u3000 從 目前 公開(kāi) 消息 來(lái)看 , 相信 是 貨幣政策 面 的 利空 預(yù)期 在 對(duì) 市場(chǎng) 形成 壓力 , 隨著 韓國(guó) 央行 的 昨日 加息 , 新興 經(jīng)濟(jì)體 緊縮 預(yù)期 驟然 升溫 , 之前 秘魯 和 泰國(guó) 已經(jīng) 有過(guò) 連續(xù) 加息 的 動(dòng)作 , 與此同時(shí) , 雖然 西方 主要 國(guó)家 仍 在 維持 寬松 , 但 隨著 發(fā)達(dá) 經(jīng)濟(jì)體 復(fù)蘇 步伐 的 加快 , 通脹 也 有 抬頭 跡象 。 國(guó)內(nèi) 方面 , 下周 可能 將 公布 2010 年 全年 和 12 月份 的 經(jīng)濟(jì)運(yùn)行 數(shù)據(jù) , 形勢(shì) 擺在 這里 , 投資者 有所 擔(dān)憂(yōu) 也 是 情理之中 。 歡迎 發(fā)表 評(píng)論 \xa0 \xa0 我要 評(píng)論'可以看到,開(kāi)頭時(shí)_label_的本文標(biāo)簽,后面接著的是新聞?wù)?#xff0c;正文已經(jīng)使用jieba進(jìn)行了分詞,詞之間使用空格鍵分開(kāi)。
下面進(jìn)行數(shù)據(jù)的切分,將數(shù)據(jù)劃分為樣本和標(biāo)簽,因?yàn)樽x取的數(shù)據(jù)是按照類(lèi)別來(lái)分塊的,在后面采用訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)的時(shí)候,會(huì)出現(xiàn)問(wèn)題,所以這里也需要進(jìn)行數(shù)據(jù)的隨機(jī)打亂,數(shù)據(jù)打亂最好不要使用numpy.random.shuffle(),這個(gè)效率很低,而且非常容易出現(xiàn)內(nèi)存溢出問(wèn)題,推薦使用的是pandas或者是sklearn中的shuffle,我使用的是后者。切分的代碼如下:
這個(gè)函數(shù)返回兩個(gè)值,其中第一個(gè)返回值input_x是樣本數(shù)據(jù),一共14*500行,第二個(gè)參數(shù)input_y和input_x有著相同的行數(shù),每行對(duì)應(yīng)著input_x中新聞樣本的類(lèi)別標(biāo)簽.
2.特征選擇
下面將進(jìn)行特征提取,特征選擇的方法有基本的bag-of-words, tf-idf,n-gran等,我們主要使用TF-IDF進(jìn)行這些方法進(jìn)行實(shí)驗(yàn),下面是代碼:
from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.cross_validation import train_test_split from sklearn.metrics.scorer import make_scorer from sklearn import linear_model from sklearn import metricsfrom time import time /usr/local/lib/python3.5/dist-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20."This module will be removed in 0.20.", DeprecationWarning) def feature_extractor(input_x, case='tfidf', max_df=1.0, min_df=0.0):"""特征抽取:param corpus: :param case: 不同的特征抽取方法:return: """return TfidfVectorizer(token_pattern='\w', ngram_range=(1,2), max_df=max_df, min_df=min_df).fit_transform(input_x)接下來(lái)將進(jìn)行訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)的切分,現(xiàn)在不進(jìn)行更好的交叉驗(yàn)證等技術(shù),僅僅簡(jiǎn)單的以一定的比例劃分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)。使用sklearn中提供的工具,具體代碼如下:
def split_data_to_train_and_test(corpus, indices=0.2, random_state=10, shuffle=True):"""將數(shù)據(jù)劃分為訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù):param corpus: [input_x]:param indices: 劃分比例:random_state: 隨機(jī)種子:param shuffle: 是否打亂數(shù)據(jù):return: """input_x, y = corpus# 切分?jǐn)?shù)據(jù)集x_train, x_dev, y_train, y_dev = train_test_split(input_x, y, test_size=indices, random_state=10)print("Vocabulary Size: {:d}".format(input_x.shape[1]))print("Train/Dev split: {:d}/{:d}".format(len(y_train), len(y_dev)))return x_train, x_dev, y_train, y_dev函數(shù)返回四個(gè)值,分別是訓(xùn)練數(shù)據(jù)的樣本,訓(xùn)練數(shù)據(jù)的標(biāo)簽,測(cè)試數(shù)據(jù)樣本,測(cè)試數(shù)據(jù)真實(shí)標(biāo)簽,下面調(diào)用樸素貝葉斯進(jìn)行分類(lèi)。
邏輯回歸是一種判別式模型,在線(xiàn)性回歸的基礎(chǔ)上,套用了一個(gè)sigmod函數(shù),這個(gè)函數(shù)講線(xiàn)性結(jié)果映射到一個(gè)概率區(qū)間,并且概率在0.5周?chē)枪饣?#xff0c;這就使得數(shù)據(jù)的分類(lèi)結(jié)果都趨向于在0,1這兩端。
LogisticRegression()主要有的參數(shù):
- penalty: 表示正則項(xiàng)為L(zhǎng)1或者L2,默認(rèn)是L2
- C 正則項(xiàng)的參數(shù)C,也就是懲罰系數(shù)
- fit_intercept 表示線(xiàn)性模型中的bias,也就是模型中的參數(shù)b 是一個(gè)布爾值,表示帶或者不帶bias,一般都是帶的!
- solver 表示的是參數(shù)學(xué)習(xí)的方法,有{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}這幾種情況,在小數(shù)據(jù)集下liblinear是相對(duì)好的選擇,在數(shù)據(jù)集大的時(shí)候,選擇saga,sag會(huì)是一個(gè)更好的選擇,但是liblinear在多分類(lèi)情況下受限制與ovr,所以其他的選擇在多分類(lèi)下更明智
這里主要是進(jìn)行相關(guān)的實(shí)驗(yàn),不在理論上展開(kāi)太多,下面采用邏輯回歸進(jìn)行文檔分類(lèi),具體代碼如下:
def fit_and_predicted(train_x, train_y, test_x, test_y, penalty='l2', C=1.0, solver='lbfgs'):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegression(penalty=penalty, C=C, solver=solver, n_jobs=-1).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))上面函數(shù)調(diào)用LogisticRegression(),基于線(xiàn)性分類(lèi)器的變種模型有很多,我們將會(huì)在后面的試驗(yàn)中使用添加了L1范式的lasso回歸,添加了L2范式的嶺回歸回歸
下面將進(jìn)行實(shí)際的代碼運(yùn)行階段了。
# 1. 加載語(yǔ)料 corpus = split_data_with_label('thu_data_1000')2.1 TF-IDF (max_df, min_df)=dafault (1.0,0.0)
input_x, y = corpus # 2. 特征選擇 input_x = feature_extractor(input_x, 'tfidf') # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) Vocabulary Size: 942969 Train/Dev split: 11200/2800 # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t\t使用 max_df,min_df=(1.0,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi)\t\t') fit_and_predicted(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0)) 使用 max_df,min_df=(1.0,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support__label__體育 0.93 0.97 0.95 186 __label__娛樂(lè) 0.87 0.88 0.88 233 __label__家居 0.88 0.90 0.89 203 __label__彩票 0.98 0.96 0.97 207 __label__房產(chǎn) 0.90 0.90 0.90 178 __label__教育 0.92 0.91 0.92 208 __label__時(shí)尚 0.92 0.92 0.92 197 __label__時(shí)政 0.83 0.87 0.85 211 __label__星座 0.94 0.97 0.95 202 __label__游戲 0.96 0.91 0.94 202 __label__社會(huì) 0.85 0.92 0.88 210 __label__科技 0.88 0.80 0.84 173 __label__股票 0.87 0.82 0.84 196 __label__財(cái)經(jīng) 0.93 0.90 0.91 194avg / total 0.90 0.90 0.90 2800accuracy_score: 0.90321s time uesed: 44.1572s可以看出邏輯回歸的文本分類(lèi)方法在該數(shù)據(jù)集上表現(xiàn)良好,綜合得分都有91%以上,下面我們將對(duì)tf-idf做文章,看看不同的tf-idf參數(shù)對(duì)特征產(chǎn)生影響
2.2 TF-IDF 不同的max_df對(duì)結(jié)果參數(shù)的影響
# 2. 特征選擇 max_df = [0.2, 0.4, 0.5, 0.8, 1.0, 1.5, 5] for i in max_df:input_x, y = corpusinput_x = feature_extractor(input_x, 'tfidf', max_df=i)# 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])# 4. 訓(xùn)練以及測(cè)試t0 = time()print('\t 使用 max_df,min_df=(%.1f,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi)\t\t\n' %(i))fit_and_predicted(train_x, train_y, test_x, test_y)print('time uesed: %0.4fs' %(time() - t0)) Vocabulary Size: 670795 Train/Dev split: 5600/1400使用 max_df,min_df=(0.2,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.95 0.95 0.95 109_娛樂(lè)_ 0.73 0.88 0.80 92_家居_ 0.98 0.88 0.93 109_彩票_ 0.99 0.96 0.97 97_房產(chǎn)_ 0.94 0.94 0.94 97_教育_ 0.94 0.89 0.92 104_時(shí)尚_ 0.87 0.87 0.87 110_時(shí)政_ 0.86 0.89 0.87 93_星座_ 0.96 0.93 0.95 105_游戲_ 0.97 0.91 0.94 103_社會(huì)_ 0.84 0.88 0.86 99_科技_ 0.85 0.86 0.86 93_股票_ 0.82 0.88 0.85 78_財(cái)經(jīng)_ 0.97 0.91 0.94 111avg / total 0.91 0.90 0.91 1400accuracy_score: 0.90429s time uesed: 63.8214s Vocabulary Size: 671113 Train/Dev split: 5600/1400使用 max_df,min_df=(0.4,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.97 0.94 0.96 109_娛樂(lè)_ 0.78 0.89 0.83 92_家居_ 0.94 0.87 0.90 109_彩票_ 0.98 0.97 0.97 97_房產(chǎn)_ 0.93 0.92 0.92 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.90 0.86 0.88 110_時(shí)政_ 0.83 0.90 0.87 93_星座_ 0.94 0.95 0.95 105_游戲_ 0.95 0.90 0.93 103_社會(huì)_ 0.86 0.90 0.88 99_科技_ 0.88 0.87 0.88 93_股票_ 0.80 0.91 0.85 78_財(cái)經(jīng)_ 0.95 0.89 0.92 111avg / total 0.91 0.91 0.91 1400accuracy_score: 0.90500s time uesed: 62.6203s Vocabulary Size: 671183 Train/Dev split: 5600/1400使用 max_df,min_df=(0.5,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.97 0.94 0.96 109_娛樂(lè)_ 0.79 0.89 0.84 92_家居_ 0.93 0.87 0.90 109_彩票_ 0.98 0.97 0.97 97_房產(chǎn)_ 0.93 0.91 0.92 97_教育_ 0.94 0.88 0.91 104_時(shí)尚_ 0.91 0.87 0.89 110_時(shí)政_ 0.83 0.89 0.86 93_星座_ 0.94 0.96 0.95 105_游戲_ 0.95 0.89 0.92 103_社會(huì)_ 0.85 0.90 0.87 99_科技_ 0.88 0.87 0.88 93_股票_ 0.80 0.91 0.85 78_財(cái)經(jīng)_ 0.94 0.88 0.91 111avg / total 0.91 0.90 0.90 1400accuracy_score: 0.90357s time uesed: 63.2442s Vocabulary Size: 671261 Train/Dev split: 5600/1400使用 max_df,min_df=(0.8,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.96 0.94 0.95 109_娛樂(lè)_ 0.79 0.88 0.83 92_家居_ 0.92 0.89 0.91 109_彩票_ 0.98 0.97 0.97 97_房產(chǎn)_ 0.93 0.91 0.92 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.91 0.87 0.89 110_時(shí)政_ 0.83 0.88 0.85 93_星座_ 0.94 0.97 0.96 105_游戲_ 0.95 0.89 0.92 103_社會(huì)_ 0.85 0.89 0.87 99_科技_ 0.88 0.85 0.86 93_股票_ 0.77 0.91 0.84 78_財(cái)經(jīng)_ 0.95 0.88 0.92 111avg / total 0.91 0.90 0.90 1400accuracy_score: 0.90143s time uesed: 64.9945s Vocabulary Size: 671267 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.95 0.94 0.94 109_娛樂(lè)_ 0.80 0.88 0.84 92_家居_ 0.95 0.89 0.92 109_彩票_ 0.98 0.95 0.96 97_房產(chǎn)_ 0.93 0.92 0.92 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.91 0.87 0.89 110_時(shí)政_ 0.81 0.90 0.85 93_星座_ 0.94 0.98 0.96 105_游戲_ 0.95 0.90 0.93 103_社會(huì)_ 0.84 0.89 0.86 99_科技_ 0.89 0.84 0.86 93_股票_ 0.76 0.91 0.83 78_財(cái)經(jīng)_ 0.96 0.87 0.92 111avg / total 0.91 0.90 0.90 1400accuracy_score: 0.90214s time uesed: 67.9015s Vocabulary Size: 671267 Train/Dev split: 5600/1400使用 max_df,min_df=(1.5,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.95 0.94 0.94 109_娛樂(lè)_ 0.80 0.88 0.84 92_家居_ 0.95 0.89 0.92 109_彩票_ 0.98 0.95 0.96 97_房產(chǎn)_ 0.93 0.92 0.92 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.91 0.87 0.89 110_時(shí)政_ 0.81 0.90 0.85 93_星座_ 0.94 0.98 0.96 105_游戲_ 0.95 0.90 0.93 103_社會(huì)_ 0.84 0.89 0.86 99_科技_ 0.89 0.84 0.86 93_股票_ 0.76 0.91 0.83 78_財(cái)經(jīng)_ 0.96 0.87 0.92 111avg / total 0.91 0.90 0.90 1400accuracy_score: 0.90214s time uesed: 66.4803s Vocabulary Size: 562057 Train/Dev split: 5600/1400使用 max_df,min_df=(5.0,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.94 0.83 0.88 109_娛樂(lè)_ 0.61 0.75 0.67 92_家居_ 0.91 0.55 0.69 109_彩票_ 0.95 0.84 0.89 97_房產(chǎn)_ 0.94 0.81 0.87 97_教育_ 0.92 0.80 0.86 104_時(shí)尚_ 0.82 0.72 0.77 110_時(shí)政_ 0.77 0.78 0.78 93_星座_ 0.86 0.75 0.80 105_游戲_ 0.96 0.72 0.82 103_社會(huì)_ 0.77 0.78 0.77 99_科技_ 0.64 0.81 0.71 93_股票_ 0.33 0.88 0.48 78_財(cái)經(jīng)_ 0.97 0.67 0.79 111avg / total 0.83 0.76 0.78 1400accuracy_score: 0.75929s time uesed: 22.6883s從實(shí)驗(yàn)結(jié)果可以看出,最好的max_df是在0.4-0.5之間,這也就是為什么很多demo中設(shè)置TF-IDF閾值進(jìn)行特征的篩選,下面設(shè)置在max_df為1.0的目標(biāo)下測(cè)試min_df;
2.2 TF-IDF 不同的min_df對(duì)結(jié)果參數(shù)的影響
# 2. 特征選擇 min_df = [0., 0.1, 0.2, 0.3, 0.4] for i in min_df:input_x, y = corpusinput_x = feature_extractor(input_x, 'tfidf', max_df=1.0, min_df=i)# 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])# 4. 訓(xùn)練以及測(cè)試t0 = time()print('\t 使用 max_df,min_df=(1.0,%.1f) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi)\t\t\n' %(i))fit_and_predicted(train_x, train_y, test_x, test_y)print('time uesed: %0.4fs' %(time() - t0)) Vocabulary Size: 671267 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.95 0.94 0.94 109_娛樂(lè)_ 0.80 0.88 0.84 92_家居_ 0.95 0.89 0.92 109_彩票_ 0.98 0.95 0.96 97_房產(chǎn)_ 0.93 0.92 0.92 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.91 0.87 0.89 110_時(shí)政_ 0.81 0.90 0.85 93_星座_ 0.94 0.98 0.96 105_游戲_ 0.95 0.90 0.93 103_社會(huì)_ 0.84 0.89 0.86 99_科技_ 0.89 0.84 0.86 93_股票_ 0.76 0.91 0.83 78_財(cái)經(jīng)_ 0.96 0.87 0.92 111avg / total 0.91 0.90 0.90 1400accuracy_score: 0.90214s time uesed: 67.8985s Vocabulary Size: 1052 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.1) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.93 0.94 0.94 109_娛樂(lè)_ 0.75 0.75 0.75 92_家居_ 0.87 0.85 0.86 109_彩票_ 0.97 0.97 0.97 97_房產(chǎn)_ 0.91 0.88 0.89 97_教育_ 0.95 0.88 0.92 104_時(shí)尚_ 0.88 0.84 0.86 110_時(shí)政_ 0.82 0.89 0.86 93_星座_ 0.93 0.96 0.94 105_游戲_ 0.95 0.88 0.91 103_社會(huì)_ 0.84 0.88 0.86 99_科技_ 0.79 0.78 0.79 93_股票_ 0.73 0.90 0.80 78_財(cái)經(jīng)_ 0.94 0.86 0.90 111avg / total 0.88 0.88 0.88 1400accuracy_score: 0.87786s time uesed: 1.8236s Vocabulary Size: 472 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.2) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.89 0.92 0.90 109_娛樂(lè)_ 0.71 0.79 0.75 92_家居_ 0.80 0.79 0.79 109_彩票_ 0.97 0.86 0.91 97_房產(chǎn)_ 0.92 0.80 0.86 97_教育_ 0.96 0.84 0.89 104_時(shí)尚_ 0.86 0.82 0.84 110_時(shí)政_ 0.77 0.84 0.80 93_星座_ 0.85 0.90 0.88 105_游戲_ 0.78 0.66 0.72 103_社會(huì)_ 0.77 0.87 0.82 99_科技_ 0.71 0.73 0.72 93_股票_ 0.65 0.83 0.73 78_財(cái)經(jīng)_ 0.92 0.85 0.88 111avg / total 0.83 0.82 0.82 1400accuracy_score: 0.82214s time uesed: 1.4046s Vocabulary Size: 244 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.3) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.87 0.89 0.88 109_娛樂(lè)_ 0.73 0.66 0.70 92_家居_ 0.81 0.74 0.78 109_彩票_ 0.90 0.84 0.87 97_房產(chǎn)_ 0.90 0.80 0.85 97_教育_ 0.84 0.78 0.81 104_時(shí)尚_ 0.78 0.83 0.81 110_時(shí)政_ 0.68 0.78 0.73 93_星座_ 0.83 0.86 0.84 105_游戲_ 0.75 0.61 0.67 103_社會(huì)_ 0.70 0.84 0.76 99_科技_ 0.69 0.72 0.71 93_股票_ 0.60 0.78 0.68 78_財(cái)經(jīng)_ 0.87 0.78 0.82 111avg / total 0.79 0.78 0.78 1400accuracy_score: 0.78143s time uesed: 1.1189s Vocabulary Size: 154 Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.4) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi) precision recall f1-score support_體育_ 0.82 0.83 0.82 109_娛樂(lè)_ 0.66 0.63 0.64 92_家居_ 0.75 0.60 0.66 109_彩票_ 0.91 0.85 0.88 97_房產(chǎn)_ 0.82 0.75 0.78 97_教育_ 0.77 0.72 0.74 104_時(shí)尚_ 0.70 0.75 0.73 110_時(shí)政_ 0.65 0.78 0.71 93_星座_ 0.85 0.86 0.85 105_游戲_ 0.63 0.57 0.60 103_社會(huì)_ 0.70 0.76 0.73 99_科技_ 0.61 0.67 0.64 93_股票_ 0.54 0.67 0.60 78_財(cái)經(jīng)_ 0.78 0.72 0.75 111avg / total 0.73 0.73 0.73 1400accuracy_score: 0.72643s time uesed: 1.0229s從上面的實(shí)驗(yàn)可以看出,min_df或許取0.0是一個(gè)不錯(cuò)的選擇,那就默認(rèn)吧。
不得不說(shuō),總感覺(jué)上面的控制變量進(jìn)行參數(shù)的尋找是有毛病的,暫且就這么做吧。在后面的試驗(yàn)中,我們將選取max_df=0.5,min_df=0.0進(jìn)行相關(guān)實(shí)驗(yàn)。
3 邏輯回歸的調(diào)參
3.1 交叉驗(yàn)證
在進(jìn)行最優(yōu)參數(shù)的調(diào)整之前,我們先看一下sklearn提供的另外一個(gè)函數(shù)LogisticRegressionCV(),它提供了標(biāo)準(zhǔn)的k-fold-cross-validator
def fit_and_predicted_use_CV(train_x, train_y, test_x, test_y, penalty='l2', C=1.0, solver='lbfgs', cv=10):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegressionCV(penalty=penalty, C=C, solver=solver, n_jobs=-1, cv=cv).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted))) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=i) # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t 使用 max_df,min_df=(%.1f,0.0) 進(jìn)行特征選擇的邏輯回歸文本分類(lèi)\t\t\n' %(i)) fit_and_predicted_use_CV(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0))可以看到使用交叉驗(yàn)證的結(jié)果往往比我們直接劃分?jǐn)?shù)據(jù)集的效果要好一些。
3.2 邏輯回歸的最佳參數(shù)尋找
現(xiàn)在將采用sklearn中提供的網(wǎng)格查找方法進(jìn)行最優(yōu)參數(shù)的尋找,網(wǎng)格查找其實(shí)是一種暴力查找方法。
import numpy as np from sklearn.grid_search import GridSearchCV def train_and_predicted_with_graid(corpus, param_grid, cv=5):input_x, y = corpusscoring = ['precision_macro', 'recall_macro', 'f1_macro']clf = linear_model.LogisticRegression(n_jobs=-1)grid = GridSearchCV(clf, param_grid, cv=cv, scoring='accuracy')scores = grid.fit(input_x, y)print('parameters:')best_parameters = grid.best_estimator_.get_params()for param_name in sorted(best_parameters):print('\t%s: %r' %(param_name, best_parameters[param_name]))return scores C= [0.1, 0.2, 0.5, 0.8, 1.5, 3, 5] fit_intercept=[True, False] penalty=['l1', 'l2'] solver=['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'] solver = ['saga'] param_grid=dict(C=C, fit_intercept=fit_intercept, penalty=penalty, solver=solver) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=0.5, min_df=0.0) scores = train_and_predicted_with_graid([input_x, y], cv=5, param_grid=param_grid) parameters:C: 5class_weight: Nonedual: Falsefit_intercept: Trueintercept_scaling: 1max_iter: 100multi_class: 'ovr'n_jobs: -1penalty: 'l2'random_state: Nonesolver: 'saga'tol: 0.0001verbose: 0warm_start: False4. 其他線(xiàn)性分類(lèi)器
4.1 簡(jiǎn)單的線(xiàn)性回歸
def fit_and_predicted_with_linerCV(train_x, train_y, test_x, test_y, alpha=1.0, cv=10):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegressionCV(penalty=penalty, C=C, solver=solver, n_jobs=-1, cv=cv).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted))) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=i) # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t 使用線(xiàn)性回歸的文本分類(lèi)\t\t\n' %(i)) fit_and_predicted_with_linerCV(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0)) {'fit_time': array([ 0.69856882, 0.6891861 , 0.68457079, 0.68122745, 0.68401599]),'score_time': array([ 0.24055672, 0.25055385, 0.24642444, 0.24583435, 0.25062966]),'test_f1_macro': array([ 0.93190598, 0.93358814, 0.92900074, 0.93620104, 0.93139325]),'test_precision_macro': array([ 0.93411186, 0.93509947, 0.93082131, 0.93790787, 0.93312355]),'test_recall_macro': array([ 0.93178571, 0.93357143, 0.92892857, 0.93607143, 0.93142857]),'train_f1_macro': array([ 0.95534592, 0.95516529, 0.95665886, 0.95573948, 0.95629695]),'train_precision_macro': array([ 0.95629235, 0.95618146, 0.95767379, 0.9566414 , 0.95725075]),'train_recall_macro': array([ 0.95526786, 0.95508929, 0.95660714, 0.95571429, 0.95625 ])}4.2 使用L1范式的Lasso
def fit_and_predicted_with_LassoCV(train_x, train_y, test_x, test_y):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LassoCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted))) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=i) # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t 使用線(xiàn)性回歸的文本分類(lèi)\t\t\n' %(i)) fit_and_predicted_with_LassoCV(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0)) {'fit_time': array([ 0.69856882, 0.6891861 , 0.68457079, 0.68122745, 0.68401599]),'score_time': array([ 0.24055672, 0.25055385, 0.24642444, 0.24583435, 0.25062966]),'test_f1_macro': array([ 0.93190598, 0.93358814, 0.92900074, 0.93620104, 0.93139325]),'test_precision_macro': array([ 0.93411186, 0.93509947, 0.93082131, 0.93790787, 0.93312355]),'test_recall_macro': array([ 0.93178571, 0.93357143, 0.92892857, 0.93607143, 0.93142857]),'train_f1_macro': array([ 0.95534592, 0.95516529, 0.95665886, 0.95573948, 0.95629695]),'train_precision_macro': array([ 0.95629235, 0.95618146, 0.95767379, 0.9566414 , 0.95725075]),'train_recall_macro': array([ 0.95526786, 0.95508929, 0.95660714, 0.95571429, 0.95625 ])}4.3 使用L2范式的嶺回歸
def fit_and_predicted_with_RidgeCV(train_x, train_y, test_x, test_y):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.RidgeClassifierCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted))) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=i) # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t 使用線(xiàn)性回歸的文本分類(lèi)\t\t\n' %(i)) fit_and_predicted_with_RidgeCV(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0)) {'fit_time': array([ 0.69856882, 0.6891861 , 0.68457079, 0.68122745, 0.68401599]),'score_time': array([ 0.24055672, 0.25055385, 0.24642444, 0.24583435, 0.25062966]),'test_f1_macro': array([ 0.93190598, 0.93358814, 0.92900074, 0.93620104, 0.93139325]),'test_precision_macro': array([ 0.93411186, 0.93509947, 0.93082131, 0.93790787, 0.93312355]),'test_recall_macro': array([ 0.93178571, 0.93357143, 0.92892857, 0.93607143, 0.93142857]),'train_f1_macro': array([ 0.95534592, 0.95516529, 0.95665886, 0.95573948, 0.95629695]),'train_precision_macro': array([ 0.95629235, 0.95618146, 0.95767379, 0.9566414 , 0.95725075]),'train_recall_macro': array([ 0.95526786, 0.95508929, 0.95660714, 0.95571429, 0.95625 ])}4.4 使用elastic net正則項(xiàng)的的線(xiàn)性回歸
def fit_and_predicted_with_ElasticNetCV(train_x, train_y, test_x, test_y):"""訓(xùn)練與預(yù)測(cè):param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.MultiTaskElasticNetCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted))) input_x, y = corpus input_x = feature_extractor(input_x, 'tfidf', max_df=i) # 3.切分訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù) train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y]) # 4. 訓(xùn)練以及測(cè)試 t0 = time() print('\t 使用線(xiàn)性回歸的文本分類(lèi)\t\t\n' %(i)) fit_and_predicted_with_ElasticNetCV(train_x, train_y, test_x, test_y) print('time uesed: %0.4fs' %(time() - t0)) {'fit_time': array([ 0.69856882, 0.6891861 , 0.68457079, 0.68122745, 0.68401599]),'score_time': array([ 0.24055672, 0.25055385, 0.24642444, 0.24583435, 0.25062966]),'test_f1_macro': array([ 0.93190598, 0.93358814, 0.92900074, 0.93620104, 0.93139325]),'test_precision_macro': array([ 0.93411186, 0.93509947, 0.93082131, 0.93790787, 0.93312355]),'test_recall_macro': array([ 0.93178571, 0.93357143, 0.92892857, 0.93607143, 0.93142857]),'train_f1_macro': array([ 0.95534592, 0.95516529, 0.95665886, 0.95573948, 0.95629695]),'train_precision_macro': array([ 0.95629235, 0.95618146, 0.95767379, 0.9566414 , 0.95725075]),'train_recall_macro': array([ 0.95526786, 0.95508929, 0.95660714, 0.95571429, 0.95625 ])}線(xiàn)性模型有很多的變種,其的簡(jiǎn)單高效并且可解釋性強(qiáng)等特點(diǎn)在機(jī)器學(xué)習(xí)領(lǐng)域有很廣泛的應(yīng)用,這里不作進(jìn)一步展開(kāi),大家自己科普吧~~
5. 總結(jié)
本文記錄了使用sklearn,采用線(xiàn)性回歸進(jìn)行文本分類(lèi)任務(wù),在特征選擇哪里,進(jìn)行TF-IDF的參數(shù)驗(yàn)證部分,找到相對(duì)較好的max_df=0.5左右;
在選取好了特征后,我們對(duì)數(shù)據(jù)集進(jìn)行交叉驗(yàn)證,發(fā)現(xiàn)交叉驗(yàn)證的方式能提高模型的效果,推薦在后面劃分?jǐn)?shù)據(jù)集的時(shí)候使用交叉驗(yàn)證。
我以邏輯回歸為例,進(jìn)行了線(xiàn)性回歸分類(lèi)器的參數(shù)搜索部分,然后利用最佳的參數(shù),訓(xùn)練了最佳的邏輯回歸文本分類(lèi)模型,模型性能的acc值能達(dá)到:91%以上
最后,我們利用其它具有代表性的線(xiàn)性分類(lèi)器進(jìn)行相關(guān)實(shí)驗(yàn),但是沒(méi)有進(jìn)行調(diào)參工作,其中L1產(chǎn)生比較離散的數(shù)值,elasticNet結(jié)合了L1,L2的優(yōu)缺點(diǎn),其在集合上的圖像介于兩者之間,效果在論文中比L1,L2都要好。
總結(jié)
以上是生活随笔為你收集整理的文本分类---逻辑回归(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【web前端特效源码】使用HTML5+C
- 下一篇: Hexo博客搭建以及主题使用