一、查準率和查全率?
查準率(Precision)(精度)是衡量某一檢索系統的信號噪聲比的一種指標,即檢出的相關文獻與檢出的全部文獻的百分比。普遍表示爲:查準率=(檢索出的相關信息量/檢索出的信息總量)x100%。
查全率(召回率),是衡量某一檢索系統從文獻集合中檢出相關文獻成功度的一項指標,即檢出的相關文獻與全部相關文獻的百分比。普遍表示爲:查全率=(檢索出的相關信息量/系統中的相關信息總量)x100%
二、ROC、混淆矩陣、F1-Score
1.ROC
一種經常與二元分類器一起使用的工具,叫做受試者工作特徵曲線(簡稱ROC)。它與精度/召回率曲線非常相似,但繪製的不是精度和召回率,而是真正類率(召回率的另一種稱呼)和假正類率(FPR)。FPR是被錯誤分爲正類的負類實例比率。它等於1-真負類率(TNR),後者正是被正確分類爲負類的負類實例比率,也稱爲奇異度。因此ROC曲線繪製的是靈敏度和(1-奇異度)的關係。
2.混淆矩陣
混淆矩陣也稱誤差矩陣,是表示精度評價的一種標準格式,用n行n列的矩陣形式來表示。具體評價指標有總體精度、製圖精度、用戶精度等,這些精度指標從不同的側面反映了圖像分類的精度。 [1] 在人工智能中,混淆矩陣(confusion matrix)是可視化工具,特別用於監督學習,在無監督學習一般叫做匹配矩陣。在圖像精度評價中,主要用於比較分類結果和實際測得值,可以把分類結果的精度顯示在一個混淆矩陣裏面。混淆矩陣是通過將每個實測像元的位置和分類與分類圖像中的相應位置和分類相比較計算的。
3.F1 Score
F1 Score,是統計學中用來衡量二分類模型精確度的一種指標。它同時兼顧了分類模型的精確率和召回率。F1分數可以看作是模型精確率和召回率的一種調和平均,它的最大值是1,最小值是0。
三、MNIST
數據介紹:一組由美國高中生和人口調查局員工手寫的70000個數字的圖片。每張圖像都用其代表的數字標記。這個數據集被廣爲使用,因此也被稱作是機器學習領域的“Hello World”:但凡有人想到了一個新的分類算法,都會想看看在MNIST上的執行結果。因此只要是學習機器學習的人,早晚都要面對MNIST。
# 使用sklearn的函數來獲取MNIST數據集
from sklearn.datasets import fetch_openml
import numpy as np
import os
# to make this notebook's output stable across runs
np.random.seed(42)
# To plot pretty figures
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
# 爲了顯示中文
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
# 耗時巨大
def sort_by_target(mnist):
reorder_train=np.array(sorted([(target,i) for i, target in enumerate(mnist.target[:60000])]))[:,1]
reorder_test=np.array(sorted([(target,i) for i, target in enumerate(mnist.target[60000:])]))[:,1]
mnist.data[:60000]=mnist.data[reorder_train]
mnist.target[:60000]=mnist.target[reorder_train]
mnist.data[60000:]=mnist.data[reorder_test+60000]
mnist.target[60000:]=mnist.target[reorder_test+60000]
mnist=fetch_openml('mnist_784',version=1,cache=True)
mnist.target=mnist.target.astype(np.int8)
sort_by_target(mnist)
mnist["data"], mnist["target"]
(array([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]),
array([0, 0, 0, ..., 9, 9, 9], dtype=int8))
mnist.data.shape
X,y=mnist["data"],mnist["target"]
X.shape
y.shape
28*28
784
# 展示圖片
def plot_digit(data):
image = data.reshape(28, 28)
plt.imshow(image, cmap = mpl.cm.binary,
interpolation="nearest")
plt.axis("off")
some_digit = X[10000]
plot_digit(X[10000].reshape(28,28))
some_digit = X[14000]
plot_digit(X[14000].reshape(28,28))
some_digit = X[22000]
plot_digit(X[22000].reshape(28,28))
some_digit = X[36000]
plot_digit(X[36000].reshape(28,28))
y[36000]
5
其他的數字的差不多,不在展示
# 更好看的圖片展示
def plot_digits(instances,images_per_row=10,**options):
size=28
# 每一行有一個
image_pre_row=min(len(instances),images_per_row)
images=[instances.reshape(size,size) for instances in instances]
# 有幾行
n_rows=(len(instances)-1) // image_pre_row+1
row_images=[]
n_empty=n_rows*image_pre_row-len(instances)
images.append(np.zeros((size,size*n_empty)))
for row in range(n_rows):
# 每一次添加一行
rimages=images[row*image_pre_row:(row+1)*image_pre_row]
# 對添加的每一行的額圖片左右連接
row_images.append(np.concatenate(rimages,axis=1))
# 對添加的每一列圖片 上下連接
image=np.concatenate(row_images,axis=0)
plt.imshow(image,cmap=mpl.cm.binary,**options)
plt.axis("off")
plt.figure(figsize=(9,9))
example_images=np.r_[X[:12000:600],X[13000:30600:600],X[30600:60000:590]]
plot_digits(example_images,images_per_row=10)
plt.show()
接下來,我們需要創建一個測試集,並把其放在一邊。
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
同樣,我們還需要對訓練集進行洗牌,這樣可以保證交叉驗證的時候,所有的摺疊都差不多。此外,有些機器學習算法對訓練示例的循序敏感,如果連續輸入許多相似的實例,可能導致執行的性能不佳。給數據洗牌,正是爲了確保這種情況不會發生。
import numpy as np
shuffer_index=np.random.permutation(60000)
X_train,y_train=X_train[shuffer_index],y_train[shuffer_index]
1.訓練一個二分類器
現在,我們先簡化問題,只嘗試識別一個數字,比如數字5,那麼這個"數字5檢測器",就是一個二分類器的例子,它只能區分兩個類別:5和非5。先爲此分類任務創建目錄標量
y_train_5=(y_train==5)
y_test_5=(y_test==5)
接着挑選一個分類器並開始訓練。一個好的選擇是隨機梯度下降(SGD)分類器,使用sklearn的SGDClassifier類即可。這個分類器的優勢是:能夠有效處理非常大型的數據集。這部分是因爲SGD獨立處理訓練實例,一次一個(這也使得SGD非常適合在線學習任務)。
from sklearn.linear_model import SGDClassifier
sgd_clf=SGDClassifier(max_iter=5,tol=-np.infty,random_state=42)
sgd_clf.fit(X_train,y_train_5)
SGDClassifier(alpha=0.0001, average=False, class_weight=None,
early_stopping=False, epsilon=0.1, eta0=0.0, fit_intercept=True,
l1_ratio=0.15, learning_rate='optimal', loss='hinge', max_iter=5,
n_iter_no_change=5, n_jobs=None, penalty='l2', power_t=0.5,
random_state=42, shuffle=True, tol=-inf, validation_fraction=0.1,
verbose=0, warm_start=False)
sgd_clf.predict([some_digit])
array([ True])
2.性能考覈
評估分類器比評估迴歸器要困難很多,因此本章將會用很多篇幅來討論這個主題,同時也會涉及許多性能考覈的方法。
3.使用交叉驗證測量精度
# 類似於分層採樣,每一折的分佈類似
from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone
skfolds = StratifiedKFold(n_splits=3, random_state=42)
for train_index, test_index in skfolds.split(X_train, y_train_5):
clone_clf = clone(sgd_clf)
X_train_folds = X_train[train_index]
y_train_folds = (y_train_5[train_index])
X_test_fold = X_train[test_index]
y_test_fold = (y_train_5[test_index])
clone_clf.fit(X_train_folds, y_train_folds)
y_pred = clone_clf.predict(X_test_fold)
n_correct = sum(y_pred == y_test_fold)
print(n_correct / len(y_pred))
0.96225
0.9645
0.94765
我們可以看到兩種交叉驗證的準確率都達到了95%上下,看起來很神奇,不過在開始激動之前,讓我們來看一個蠢笨的分類器,將所有圖片都預測爲‘非5’
from sklearn.base import BaseEstimator
# 隨機預測模型
class Never5Classifier(BaseEstimator):
def fit(self, X, y=None):
pass
def predict(self, X):
return np.zeros((len(X), 1), dtype=bool)
never_5_clf = Never5Classifier()
cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring="accuracy")
準確率也超過了90%!這是因爲我們只有大約10%的圖像是數字5,所以只要猜一張圖片不是5,那麼有90%的時間都是正確的,簡直超過了大預言家。
這說明,準確率通常無法成爲分類器的首要性能指標,特別是當我們處理偏斜數據集的時候(也就是某些類別比其他類更加頻繁的時候)