scikit-learn簡介
scikit-learn是Python最為流行的一個(gè)機(jī)器學(xué)習(xí)庫。它具有如下吸引人的特點(diǎn):
簡單、高效且異常豐富的數(shù)據(jù)挖掘/數(shù)據(jù)分析算法實(shí)現(xiàn);
基于NumPy,SciPy,以及matplotlib,從數(shù)據(jù)探索性分析,數(shù)據(jù)可視化到算法實(shí)現(xiàn),整個(gè)過程一體化實(shí)現(xiàn);
尤其是當(dāng)我們要進(jìn)行多種算法的效果對(duì)比評(píng)價(jià),這種一體化實(shí)現(xiàn)的優(yōu)勢(shì)就更加能夠凸顯出來了。
既然scikit-learn模塊如此重要,廢話不多說,下面馬上開搞!
項(xiàng)目組織及文件加載
項(xiàng)目組織
工作路徑:`D:\my_python_workfile\Thesis\sklearn_exercise` |--data:用于存放數(shù)據(jù) |--20news-bydate:練習(xí)用數(shù)據(jù)集 |--20news-bydate-train:訓(xùn)練集 |--20news-bydate-test:測(cè)試集
文件加載
假設(shè)我們需要加載的數(shù)據(jù),組織結(jié)構(gòu)如下:
container_folder/ category_1_folder/ file_1.txt file_2.txt ... file_42.txt category_2_folder/ file_43.txt file_44.txt ...
可以使用以下函數(shù)進(jìn)行數(shù)據(jù)的加載:
sklearn.datasets.load_files(container_path, description=None, categories=None, load_content=True, shuffle=True, encoding=None, decode_error='strict', random_state=0)
參數(shù)解釋:
`container_path`:container_folder的路徑;
`load_content = True`:是否把文件中的內(nèi)容加載到內(nèi)存;
`encoding = None`:編碼方式。當(dāng)前文本文件的編碼方式一般為“utf-8”,如果不指明編碼方式(encoding=None),那么文件內(nèi)容將會(huì)按照bytes處理,而不是unicode處理。
返回值:Bunch Dictionary-like object.主要屬性有
data:原始數(shù)據(jù);
filenames:每個(gè)文件的名字;
target:類別標(biāo)簽(從0開始的整數(shù)索引);
target_names:類別標(biāo)簽的具體含義(由子文件夾的名字`category_1_folder`等決定)。
下面,即采用這種方式,使用測(cè)試數(shù)據(jù)集[The 20 Newsgroups data set](Home Page for 20 Newsgroups Data Set:http://qwone.com/~jason/20Newsgroups/)進(jìn)行實(shí)例演示。先從網(wǎng)上下載該數(shù)據(jù)集,再在本地進(jìn)行數(shù)據(jù)的加載。
```python# 加載庫import osimport sys##配置utf-8輸出環(huán)境#reload(sys)#sys.setdefaultencoding("utf-8")# 設(shè)置當(dāng)前工作路徑os.chdir("D:\\my_python_workfile\\Thesis\\sklearn_exercise")# 加載數(shù)據(jù)from sklearn import datasetstwenty_train = datasets.load_files("data/20news-bydate/20news-bydate-train")twenty_test = datasets.load_files("data/20news-bydate/20news-bydate-test")``````pythonlen(twenty_train.target_names),len(twenty_train.data),len(twenty_train.filenames),len(twenty_test.data)```
(20, 11314, 11314, 7532)
```python print("\n".join(twenty_train.data[0].split("\n")[:3])) ```
From: cubbie@garnet.berkeley.edu ( )
Subject: Re: Cubs behind Marlins? How?
Article-I.D.: agate.1pt592$f9a
```python print(twenty_train.target_names[twenty_train.target[0]]) ```
rec.sport.baseball
```python twenty_train.target[:10] ```
array([ 9, 4, 11, 4, 0, 4, 5, 5, 13, 12])
可見,文件已經(jīng)被成功載入。
當(dāng)然,作為入門的訓(xùn)練,我們也可以使用`scikit-learn`自帶的`toy example`數(shù)據(jù)集進(jìn)行測(cè)試、玩耍。下面,介紹一下如何加載自帶的數(shù)據(jù)集。
```python from sklearn.datasets import fetch_20newsgroups categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med'] twenty_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42) ```文本特征提取
文本數(shù)據(jù)屬于非結(jié)構(gòu)化的數(shù)據(jù),一般要轉(zhuǎn)換成結(jié)構(gòu)化的數(shù)據(jù),方能進(jìn)行實(shí)施機(jī)器學(xué)習(xí)算法實(shí)現(xiàn)文本分類。
常見的做法是將文本轉(zhuǎn)換成『文檔-詞項(xiàng)矩陣』。矩陣中的元素,可以使用詞頻,或者TF-IDF值等。
計(jì)算詞頻
```python from sklearn.feature_extraction.text import CountVectorizer count_vect = CountVectorizer(stop_words="english",decode_error='ignore') X_train_counts = count_vect.fit_transform(twenty_train.data) X_train_counts.shape ```
(11314, 129783)
使用TF-IDF進(jìn)行特征提取
```python from sklearn.feature_extraction.text import TfidfTransformer tf_transformer = TfidfTransformer(use_idf = False).fit(X_train_counts) X_train_tf = tf_transformer.transform(X_train_counts) X_train_tf.shape ```
(11314, 129783)
以上程序使用了兩步進(jìn)行文本的形式化表示:先用`fit()`方法使得模型適用數(shù)據(jù);再用`transform()`方法把詞頻矩陣重新表述成TF-IDF.
如下所示,也可以一步到位進(jìn)行設(shè)置。
```python tfidf_transformer = TfidfTransformer() X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts) X_train_tfidf.shape ```
(11314, 129783)]
分類器訓(xùn)練
```python from sklearn.naive_bayes import MultinomialNB clf = MultinomialNB().fit(X_train_tfidf,twenty_train.target) ``````python # 對(duì)新的樣本進(jìn)行預(yù)測(cè) docs_new = ['God is love','OpenGL on the GPU is fast'] X_new_counts = count_vect.transform(docs_new) X_new_tfidf = tfidf_transformer.transform(X_new_counts) predicted = clf.predict(X_new_tfidf) for doc,category in zip(docs_new,predicted): print("%r => %s") %(doc,twenty_train.target_names[category]) ```
'God is love' => soc.religion.christian
'OpenGL on the GPU is fast' => comp.graphics
分類效果評(píng)價(jià)
建立管道
```python from sklearn.pipeline import Pipeline text_clf = Pipeline([('vect',CountVectorizer(stop_words="english",decode_error='ignore')), ('tfidf',TfidfTransformer()), ('clf',MultinomialNB()), ]) text_clf = text_clf.fit(twenty_train.data,twenty_train.target) ```
測(cè)試集分類準(zhǔn)確率
```python import numpy as np docs_test = twenty_test.data predicted = text_clf.predict(docs_test) np.mean(predicted == twenty_test.target) ```
0.81691449814126393
使用樸素貝葉斯分類器,得到的測(cè)試集分類準(zhǔn)確率為81.7%,效果還不錯(cuò)!
下面,使用線性核支持向量機(jī)看看效果如何。
```python from sklearn.linear_model import SGDClassifier text_clf_2 = Pipeline([('vect',CountVectorizer(stop_words='english',decode_error='ignore')), ('tfidf',TfidfTransformer()), ('clf',SGDClassifier(loss = 'hinge',penalty = 'l2', alpha = 1e-3,n_iter = 5, random_state = 42)), ]) _ = text_clf_2.fit(twenty_train.data,twenty_train.target) predicted = text_clf_2.predict(docs_test) np.mean(predicted == twenty_test.target) ```
0.82355284121083383
支持向量機(jī)的分類準(zhǔn)確率有所提升。
`scikit-learn`中提供了更精細(xì)化的評(píng)價(jià)指標(biāo),如:各類別的精確度,召回率,F(xiàn)值等。
下面,我們來看看更詳細(xì)的指標(biāo)表現(xiàn)如何。
```python from sklearn import metrics print(metrics.classification_report(twenty_test.target,predicted, target_names = twenty_test.target_names)) ```
precision recall f1-score support
alt.atheism 0.71 0.71 0.71 319
comp.graphics 0.81 0.69 0.74 389
comp.os.ms-windows.misc 0.72 0.79 0.75 394
comp.sys.ibm.pc.hardware 0.73 0.66 0.69 392
comp.sys.mac.hardware 0.82 0.83 0.82 385
comp.windows.x 0.86 0.77 0.81 395
misc.forsale 0.80 0.87 0.84 390
rec.autos 0.91 0.90 0.90 396
rec.motorcycles 0.93 0.97 0.95 398
rec.sport.baseball 0.88 0.91 0.90 397
rec.sport.hockey 0.87 0.98 0.92 399
sci.crypt 0.85 0.96 0.90 396
sci.electronics 0.80 0.62 0.70 393
sci.med 0.90 0.87 0.88 396
sci.space 0.84 0.96 0.90 394
soc.religion.christian 0.75 0.93 0.83 398
talk.politics.guns 0.70 0.93 0.80 364
talk.politics.mideast 0.92 0.92 0.92 376
talk.politics.misc 0.89 0.56 0.69 310
talk.religion.misc 0.81 0.39 0.53 251
avg / total 0.83 0.82 0.82 7532
測(cè)試集的精確度和召回率的表現(xiàn)均不錯(cuò).
下面看看『混淆矩陣』的結(jié)果。
```python metrics.confusion_matrix(twenty_test.target,predicted) ```使用網(wǎng)格搜索進(jìn)行參數(shù)優(yōu)化
我們使用分類器進(jìn)行文本分類的過程中,有些參數(shù)需要預(yù)先給定。如前面`TfidfTransformer()`中的`use_idf`;`MultinomialNB()`中的平滑參數(shù)`alpha`;`SGClassifier()`中的懲罰系數(shù)`alpha`。然而,參數(shù)設(shè)置為多少,并不能直接拍腦袋決定。因?yàn)閰?shù)的設(shè)置可能會(huì)導(dǎo)致結(jié)果天差地別。
為了不淪落為一個(gè)『調(diào)參狗』,我們來看看如何使用暴力的『網(wǎng)格搜索算法』讓計(jì)算機(jī)幫我們進(jìn)行參數(shù)尋優(yōu)。
```python from sklearn.grid_search import GridSearchCV parameters = { 'vect__ngram_range':[(1,1),(1,2)], 'tfidf__use_idf':(True,False), 'clf__alpha':(1e-2,1e-3) } ```
如果要窮盡所有參數(shù)的組合,那勢(shì)必要花費(fèi)很多時(shí)間來等待結(jié)果。有的『土豪』同學(xué)可能會(huì)想:我能不能用金錢來換時(shí)間?
答案是肯定的。如果你有一臺(tái)8核的電腦,那就把所有的核都用上吧!
```python gs_clf = GridSearchCV(text_clf_2,parameters,n_jobs = -1) ``` ```python gs_clf = gs_clf.fit(twenty_train.data,twenty_train.target) ```
設(shè)置`n_jobs = -1`,計(jì)算機(jī)就會(huì)幫你自動(dòng)檢測(cè)并用上你所有的核進(jìn)行并行計(jì)算。
```python best_parameters,score,_ = max(gs_clf.grid_scores_,key = lambda x:x[1]) for param_name in sorted(parameters.keys()): print("%s: %r" %(param_name,best_parameters[param_name])) ```
clf__alpha: 0.01
tfidf__use_idf: True
vect__ngram_range: (1, 1)
```python score ```
0.90516174650875025
-
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8423瀏覽量
132744 -
數(shù)據(jù)可視化
+關(guān)注
關(guān)注
0文章
467瀏覽量
10311 -
算法實(shí)現(xiàn)
+關(guān)注
關(guān)注
1文章
3瀏覽量
1857
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論