日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)

發布時間:2024/1/17 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一節三節講述了真實數據(csv表格數據)的一個實戰操作的總流程,然而這個處理是一個回歸模型,即目標是一些連續的值(median_house_value)。當目標是一些有限的離散值得時候(比如數字0-9),就變成了分類問題,下面開始講述分類問題。

四、分類問題

??下面將使用新的具有代表性的數據集MNIST(手寫體數字數據集),數據集總共有70000個小圖片,每個小圖片為一個手寫的數字,(數據中0代表白,1代表黑),數據中把28*28個像素拉成一個向量作為特征,寫的數字作為label。?


1、關于MNIST數據集

??Scikit-learn提供了MNIST數據的下載,如果下載不了也可以自行網站上下載。

from sklearn.datasets import fetch_mldata mnist = fetch_mldata('MNIST original')
  • 1
  • 2

??下載完成后可以輸入mnist自行查看一下數據的結構,還可以使用matplotlib輸出一張圖片看看。

??下面需要劃分訓練集和測試集,MNIST數據集已經幫我們劃分好(前60000個為訓練集,后10000個位測試集)

X, y = mnist["data"], mnist["target"] X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
  • 1
  • 2

??雖然MNIST數據集中已經把訓練測試集分好,但是還未打亂(shuffle),所以需要對訓練集進行打亂。

import numpy as np shuffle_index = np.random.permutation(60000) X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
  • 1
  • 2
  • 3



2、二分類

??假設現在分類是否為數字5,則分類兩類(是5或不是5),訓練一個SGD分類器(該分類器對大規模的數據處理較快)。

#劃分數據 y_train_5 = (y_train == 5) y_test_5 = (y_test == 5) #訓練模型 from sklearn.linear_model import SGDClassifier sgd_clf = SGDClassifier(random_state=42) sgd_clf.fit(X_train, y_train_5) #交叉驗證 from sklearn.model_selection import cross_val_predict y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10



查準率和查全率(Precision and Recall)以及F1指標

??與回歸問題計算損失函數不同,二分類特有的一種評價指標為查準率和查全率(Precision and Recall)以及F1指標。

??Precision就是預測為正類的樣本有多少比例的樣本是真的正類,TP/(TP+FP);Recall就是所有真正的正類樣本有多少比例被預測為正類,TP/(TP+FN)。其中TP為真正類被預測為正類,FP為負類被預測為正類,FN為真正類被預測為負類。Scikit-learn也有對應的函數

from sklearn.metrics import precision_score, recall_score precision_score(y_train_5, y_train_pred) recall_score(y_train_5, y_train_pred)
  • 1
  • 2
  • 3

??由于Precision和Recall有兩個數,如果一大一下的話不好比較兩個模型的好壞,F1指標就是結合兩者,求調和平均

F1=2?Precision?RecallPrecision+RecallF1=2?Precision?Re?callPrecision+Re?call

from sklearn.metrics import f1_score f1_score(y_train_5, y_train_pred)
  • 1
  • 2

??對于F1值,暗含了Precision和Recall是同等重要的,然而對于現實問題并不一定同等重要,比如推薦電影,給觀眾推薦一部很好的電影比很多電影更重要,因此Precision更加重要;而對于檢查安全問題,寧可多次去核查也不能出現一點錯誤,因此Recall更重要。所以對于實際問題,應該適當權衡Precision和Recall。?


Precision/Recall 的權衡

??雖然我們沒有辦法改變Scikit-learn里面的predict()函數來改變分類輸出,但我們能夠通過decision_function()方法來得到輸出的得分情況,得分越高意味著越有把握分為這一類。因此可以通過對得分設一個界(threshold),得分大于threshod的分為正類,否則為負類,以此來調整Precision和Recall。

??然而這個threhold應該怎么確定,scikit-learn中提供相關的函數precision_recall_curve()來幫助我們確定。

??需要注意:cross_val_predict計算交叉驗證后驗證集部分的得分(而不是類別)。

#計算得分 from sklearn.model_selection import cross_val_predict y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function") #調用precision_recall_curve from sklearn.metrics import precision_recall_curve precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

??需要注意:得出的結果precisions和recalls的元素個數比threholds多一個,因此畫圖時需要回退一個。

??將結果通過圖展示出來

import matplotlib.pyplot as plt def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):plt.plot(thresholds, precisions[:-1], "b--", label="Precision")plt.plot(thresholds, recalls[:-1], "g-", label="Recall")plt.xlabel("Threshold")plt.legend(loc="upper left")plt.ylim([0, 1]) plot_precision_recall_vs_threshold(precisions, recalls, thresholds) plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

??????????

??觀察圖,按需要選擇合適的Threshold。?


3、多分類

??對于隨機森林分類器(Random Forest classifiers)和樸素貝葉斯分類器(naive Bayes classifiers),本來就能夠處理多分類的問題。但是有一些算法如支撐向量機(Support Vector Machine classifier)和線性分類器(Linear classifiers)就是二分類器。將二分類器擴展到多分類器一般有兩種做法。

??1、OVA(one-versus-all):比如分類數字(0-9),則訓練10個分類器(是否為0的分類器,是否為1的分類器.,…,是否為9的分類器),每一個分類器最后會算出一個得分,判定為最高分的那一類

??2、OVO(one-versus-one):每個類之間訓練一個分類器(比如0和1訓練一個分類器,1-3訓練一個分類器),這樣總共有N*(N-1)/2個分類器,哪個類得分最高判定為那一類。

??一般情況下,OVO訓練速度比較快(因為訓練多個小分類器比訓練一個大分類器時間要快),而OVA的表現會更好,因此Scikit-learn中二分類器進行多分類默認為OVA,除了支撐向量機使用OVO以外(由于支撐向量機對大規模的數據表現不好)

??下面是一個二分類器SGD分類器擴展為多分類器用作數字分類的例子

from sklearn.linear_model import SGDClassifier sgd_clf = SGDClassifier(random_state=42) sgd_clf.fit(X_train, y_train)
  • 1
  • 2
  • 3

??可以隨便取一個數據看看得分情況

some_digit = X[36000] sgd_clf.predict([some_digit]) some_digit_scores = sgd_clf.decision_function([some_digit])
  • 1
  • 2
  • 3

??

??可以看到第6個分數(代表數字5)最高,即分類為數字5。

??這是OVA的情況,也可以強制變為OVO(OVA)的情況OneVsOneClassifier(OneVsRestClassifier)?


4、評價分類器的好壞

??對于回歸任務,上一節評價模型的好壞用的是交叉驗證法,對于分類任務,同樣也可以采取交叉驗證法,不同的是,誤差不是均方誤差,而是準確率(或者交叉熵)。和之前交叉驗證的函數相同為cross_val_score,不過scoring為accuracy。

from sklearn.model_selection import cross_val_score cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring="accuracy")
  • 1
  • 2

??結果為:?
??

??可以看到準確率大概在86%,當然也可以采用預處理(標準化)來增加準確率。

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train.astype(np.float64)) cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring="accuracy")
  • 1
  • 2
  • 3
  • 4

??結果為:?
??

??可以看到經過標準化后準確率上升到了90%?


5、錯誤分析

??當然,如果這是一個真正的項目,還需要嘗試多個模型,選擇最佳模型并微調超參數,現在假設已經找到了這個模型,并想進一步提升,其中一種方法是分析錯誤的類型是哪些。

混淆矩陣法

??首先要使用cross_val_predict計算交叉驗證后驗證集部分的預測分類結果(而不是正確率),然后根據真正的標簽和預測結果對比,畫出混淆矩陣(如下圖),第 i 行第 j 列的數字代表數字 i 被預測為數字 j 的個數總和,比如第5行第一個數表示數字4被誤判為0的次數為75;對角線上即為正確分類的次數。

from sklearn.model_selection import cross_val_predict from sklearn.metrics import confusion_matrix y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3) conf_mx = confusion_matrix(y_train, y_train_pred) conf_mx
  • 1
  • 2
  • 3
  • 4
  • 5

??

??然而矩陣中數據太多很復雜,所以可以通過圖更加直觀地表示出來

plt.matshow(conf_mx, cmap=plt.cm.gray) plt.show()
  • 1
  • 2

????????????????

??從圖中可以看到分類結果表現的還好,數字5比較暗,說明數字5被錯分的比較多。

??還可以去除正確的對角線的分布情況,只看錯誤的分布

row_sums = conf_mx.sum(axis=1, keepdims=True) norm_conf_mx = conf_mx / row_sums.astype(np.float64) np.fill_diagonal(norm_conf_mx, 0) plt.matshow(norm_conf_mx, cmap=plt.cm.gray) plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5

????????????????

??可以看到第6行第4列與第4行第6列種比較白,說明5錯分為3,3錯分為5的次數比較多。因此還可以把錯誤分為3和5的樣本提取出來觀察分析,從而改進算法。?


6、多標簽分類(Multilabel Classification)

??直到現在的例子都是將數據分為某一類,但有些時候想分為多個類(比如人臉識別分類器,如果一張圖片上有多個人臉,那就不能只識別一個人,而是要識別出多個人),輸出比如為[1,0,1],則分為1和3類。對于這種輸出多個二值分類標簽的就是多標簽分類。下面是一個簡單的例子:

from sklearn.neighbors import KNeighborsClassifier y_train_large = (y_train >= 7) y_train_odd = (y_train % 2 == 1) y_multilabel = np.c_[y_train_large, y_train_odd] knn_clf = KNeighborsClassifier() knn_clf.fit(X_train, y_multilabel) knn_clf.predict([some_digit])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

??

??例子中的任務是:分類數據 是否大于等于7 以及 是否為奇數 這2個標簽,使用k-近鄰分類器(KNN)進行多標簽分類(不是所有的分類器都能進行多標簽分類)。

??評價多標簽分類模型的方法可以對每種標簽求F1值,再求平均值。?


7、多輸出分類(Multioutput Classification)

??多輸出分類是多標簽分類更一般的一種形式,比如現在圖像有噪聲,需要將每個像素分類為0或1已達到去噪的目的(也可以多個標簽)。下面就是一個例子,如下圖,左圖為的像素為特征,右圖為標簽。

#生成左邊的噪聲圖 import numpy.random as rnd noise1 = rnd.randint(0, 100, (len(X_train), 784)) noise2 = rnd.randint(0, 100, (len(X_test), 784)) X_train_mod = X_train + noise1 X_test_mod = X_test + noise2 y_train_mod = X_train y_test_mod = X_test import matplotlib.pyplot as plt plt.subplot(1,2,1) plt.imshow(X_train_mod[36000].reshape(28,28),cmap=plt.cm.gray) plt.subplot(1,2,2) plt.imshow(X_train[36000].reshape(28,28),cmap=plt.cm.gray)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

????????????

??接下來訓練一個KNN模型實現多輸出分類(去噪)

from sklearn.neighbors import KNeighborsClassifier knn_clf = KNeighborsClassifier() knn_clf.fit(X_train_mod, y_train_mod) clean_digit = knn_clf.predict([X_train_mod[36000]]) plt.imshow(clean_digit.reshape(28,28),cmap=plt.cm.gray)
  • 1
  • 2
  • 3
  • 4
  • 5

????????????

??可以看到訓練的模型能夠對每個像素進行分類,從而實現去噪。?

總結

以上是生活随笔為你收集整理的机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。