人工智慧:有監督學習分類與回歸
本節內容翻譯自東南大學出版社出版的《人工智慧:Python實現(影印版)》第2章內容。
本節將使用監督學習技術來學習數據的分類具體包括:有監督學習和無監督學習,分類的含義,多種數據預處理方法,標籤編碼,邏輯斯特回歸分類器,樸素貝葉斯分類器,混淆矩陣,支持向量機、單變數和多變數線性回歸器、支持向量回歸機等。
1有監督學習與無監督學習
機器學習是當前人工智慧發展的加速器,由機器學習延伸的深度學習表現出異常出色的性能,將實際中的很多問題落地解決。機器學習方法大致可分為有監督學習和無監督學習兩種。當然,還有半監督學習等方法在以後的內容中討論。有監督學習是指基於有標記的訓練數據建立機器學習模型的過程。例如,假設我們要建立一個雷達目標識別系統,根據各種觀測參數(如大小、速度、外觀、形狀等)自動識別目標類別。那麼,我們需要創建一個包含所有必要細節的雷達目標資料庫並對其進行標記,演算法根據輸入數據和已標記類別學習一個映射,完成給定輸入數據預測目標類別的功能。無監督學習是指基於無標記的訓練數據建立機器學習模型的過程。從某種意義上說,由於沒有可用標籤,因此可根據數據本身的特徵學習模型。例如,假設我們要建立一個目標數據管理系統,需要將無標籤的數據分成若干組,以方便數據的管理。無監督學習的難點在於在學習的標準是未知的,需要儘可能以最好的方式將給定的數據分成若干組。
2分類的含義
有監督學習中的一大主要任務就是分類技術。分類就是將數據劃分到已知的若干個類中的一種技術。在機器學習中,分類解決了判定新數據點所屬類別的問題。基於給定數據和標籤的訓練數據集建立分類模型。例如,判定給定的一幅圖像是否包含人臉。首先,需要構建一個訓練數據集,包含人臉和不是人臉兩類圖像。然後,根據訓練樣本來訓練模型。最後,將訓練好的模型用於預測推斷。一個好的分類系統可以準確地預測給定數據的類別。分類技術被廣泛用於人臉識別、垃圾郵件識別、推薦引擎等應用中。
基於學習的分類技術需要提供足夠多的樣本,以便能夠推廣模型的能力。如果樣本數量不足,那麼模型可能會過擬合訓練數據,這極有可能導致其在未知數據上表現不佳。過擬合是機器學習領域中一個非常普遍的問題,因為模型對數據進行了過渡的學習以至於無法適應訓練數據中未觀察到的模式。在訓練各種機器學習模型時,這個因素是必須考慮和值得注意的。
3數據預處理
現實世界中存在的大量原始數據是無法直接用於機器學習演算法的。機器學習演算法希望在訓練模型前對數據進行一定的格式化。為了準備機器學習演算法輸入的數據,必須對數據進行預處理並將其轉換為正確的格式。常用的數據格式化方法主要有:
l二值化
l平均去除
l縮放
l正常化
為了更好地示例化講解,我們選擇在Python環境下,基於numpy和sklearn進行數據格式化。首先,導入相關開發包:
import numpy as np
from sklearn importpreprocessing
然後,定義如下示例數據:
input_data =np.array([[5.1, -2.9, 3.3],
[-1.2, 7.8, -6.1],
[3.9, 0.4, 2.1],
[7.3, -9.9, -4.5]])
接下來一一介紹上面的幾種的預處理技術。
二值化
二值化主要用於將實數值轉換為布爾值。
對於上面的示例數據,可直接使用內置Binarizer方法對輸入數據進行二值化:
# Binarize data
data_binarized =preprocessing.Binarizer(threshold=2.1).transform(input_data)
print("
Binarizeddata:
", data_binarized)
其中threshold=2.1表示以2.1作為閾值,大於等於2.1的數值轉化為,小於2.1的數值轉化為1。輸出結果如下:
Binarized data:
[[1. 0. 1.]
[0. 1. 0.]
[1. 0. 0.]
[1. 0. 0.]]
去除平均值
去除平均值就是從特徵向量中去除均值,使得每個特徵都以零為中心,消除特徵向量中的特徵偏差。它是機器學習中常用的預處理技術。
對於上面的示例數據,可直接使用內置scale方法對輸入數據進行去除平均值:
# Print mean andstandard deviation
print("
BEFORE:")
print("Mean=", input_data.mean(axis=0))
print("Stddeviation =", input_data.std(axis=0))
# Remove mean
data_scaled =preprocessing.scale(input_data)
print("
AFTER:")
print("Mean=", data_scaled.mean(axis=0))
print("Stddeviation =", data_scaled.std(axis=0))
其中,前三行顯示輸入數據的平均值和標準偏差,後三行顯示去除平均值後數據的平均值和標準偏差。
運行代碼,輸出以下內容:
BEFORE:
Mean = [ 3.775-1.15 -1.3 ]
AFTER:
Std deviation = [1. 1.1.]
從結果可以看出,操作後數據的平均值非常接近,且標準偏差為1。
縮放
在數據測量中,由於特徵計量的差異,有的特徵數值非常大,而另一些特徵數值非常小,這就導致數據特徵向量中不同維度上的值可能存在較大的差異。為了給不同維度上的數值提供一個公平的競爭環境,對數據進行縮放操作是非常必要的。我們不希望僅僅因為測量的原因使得特徵被人為設置的過大或過小。
對於上面的示例數據,可直接使用內置MinMaxScaler方法對輸入數據進行縮放:
# Min max scaling
data_scaler_minmax =preprocessing.MinMaxScaler(feature_range=(0, 1))
data_scaled_minmax =data_scaler_minmax.fit_transform(input_data)
print("
Min maxscaled data:
", data_scaled_minmax)
運行代碼,得到如下結果:
Min max scaled data:
[0. 1. 0. ]
由結果可見,每行的最大值為1,所有其他值都相對於此值進行了縮放。
歸一化
歸一化也稱為標準化,通過修改特徵向量中的值,使得不同樣本數據可以在一個共同的尺度上對它們進行測量。在機器學習中,歸一化有多種形式,最常見的形式就是通過改變樣本數據的值,使它們總和為1。例如:L1歸一化,即最小絕對偏差,使每個樣本數據的絕對值總和為1。L2歸一化,即最小二乘法,使每個樣本數據的平方和為1。通常,L1歸一化技術被認為比L2歸一化技術更穩健,因為L1歸一化可以抵抗數據中的異常值。很多時候,數據往往含有異常值,導致無法做任何事情。故而希望在計算過程中能夠安全有效地忽略它們。但是,如果問題是一個異常值很重要的問題,那麼L2標準化可能是一個更好的選擇。
對於上面的示例數據,可直接使用內置normalize方法對輸入數據分別進行L1和L2歸一化:
# Normalize data
data_normalized_l1 =preprocessing.normalize(input_data, norm="l1")
data_normalized_l2 =preprocessing.normalize(input_data, norm="l2")
print("
L1normalized data:
", data_normalized_l1)
print("
L2normalized data:
", data_normalized_l2)
輸出結果如下:
L1 normalized data:
[ 0.609375 0.0625 0.328125 ]
L2 normalized data:
4標籤編碼
有監督學習分類時,標籤是必不可少的信息。實際中,這些標籤可以是文字,數字或其他形式。sklearn中的機器學習函數期望它們是數字。因此,如果標籤不是數字,那麼就需要將他們表示為數字。
在現實世界中,標籤通常是以單詞形式出現的,以便於人類的辨識和記憶。要將單詞標籤轉換為數字,我們需要對標籤進行編碼。標籤編碼是指將單詞標籤轉換為數字形式的過程。基於sklearn對標籤進行編碼,導入相關Python包:
from sklearn importpreprocessing
定義一些樣本標籤:
# Sample input labels
input_labels = ["red","black", "red", "green", "black", "yellow", "white"]
創建標籤編碼器對象並訓練之:
# Create label encoderand fit the labels
encoder =preprocessing.LabelEncoder()
encoder.fit(input_labels)
輸出單詞和數字之間的映射:
# Print the mapping
print("
Labelmapping:")
for i, item inenumerate(encoder.classes_):
print(item, "-->", i)
輸出結果如下:
Label mapping:
black --> 0
green --> 1
white --> 3
yellow --> 4
下面編碼一組隨機排序的標籤:
# Encode a set of labelsusing the encoder
test_labels = ["green","red", "black"]
encoded_values =encoder.transform(test_labels)
print("
Labels=", test_labels)
print("Encodedvalues =", list(encoded_values))
輸出結果如下:
Labels = ["green","red", "black"]
Encoded values = [1, 2,0]
讓我們來解碼一組隨機數字:
# Decode a set of valuesusing the encoder
encoded_values = [3, 0,4, 1]
decoded_list =encoder.inverse_transform(encoded_values)
print("
Encodedvalues =", encoded_values)
print("Decodedlabels =", list(decoded_list))
輸出結果如下:
Encoded values = [3, 0,4, 1]
Decoded labels =["white", "black", "yellow", "green"]
任務2:檢查映射的編碼和解碼步驟是否正確。
5邏輯斯特回歸
邏輯斯特(Logistic)回歸是一種分類器,雖然其名稱中帶有「回歸」兩字。該分類器用於建模輸入變數和輸出變數之間的關係。通常輸入變數是獨立的自變數,輸出變數只能取一組固定的離散值,對應於分類問題的類別。
邏輯斯特(Logistic)回歸的目標是通過使用邏輯函數估計概率來確定自變數和因變數之間的關係。這個邏輯函數是一個sigmoid曲線,用來構建具有各種參數的函數。它與廣義線性模型分析密切相關,我們試圖將一條線與一組點相吻合以最小化誤差。我們不使用線性回歸,而是使用邏輯斯特回歸。邏輯回歸本身實際上不是一種分類技術,但是我們以這種方式使用它來促進分類,故而稱為邏輯斯特(Logistic)回歸。由於其簡單性,它在機器學習中應用非常普遍。
導入下列軟體包:
import numpy as np
from sklearn importlinear_model
import matplotlib.pyplotas plt
用二維向量和相應的標籤定義樣本輸入數據:
# Define sample inputdata
X = np.array([[3.1,7.2], [4, 6.7], [2.9, 8], [5.1, 4.5], [6, 5], [5.6, 5], [3.3, 0.4], [3.9, 0.9],[2.8, 1], [0.5, 3.4], [1, 4], [0.6, 4.9]])
y = np.array([0, 0, 0,1, 1, 1, 2, 2, 2, 3, 3, 3])
使用以上數據來訓練分類器。先創建邏輯回歸分類器對象:
# Create the logisticregression classifier
classifier =linear_model.LogisticRegression(solver="liblinear", C=1)
使用數據訓練分類器:
# Train the classifier
classifier.fit(X, y)
通過查看類的邊界來可視化分類器的性能:
# Visualize theperformance of the classifier
visualize_classifier(classifier,X, y)
其中,函數visualize_classifier定義如下:
defvisualize_classifier(classifier, X, y):
# Define the minimum and maximum values forX and Y
# that will be used in the mesh grid
min_x, max_x = X[:, 0].min() - 1.0, X[:,0].max() + 1.0
min_y, max_y = X[:, 1].min() - 1.0, X[:,1].max() + 1.0
# Define the step size to use in plottingthe mesh grid
mesh_step_size = 0.01
# Define the mesh grid of X and Y values
x_vals, y_vals =np.meshgrid(np.arange(min_x, max_x, mesh_step_size), np.arange(min_y, max_y,mesh_step_size))
# Run the classifier on the mesh grid
output =classifier.predict(np.c_[x_vals.ravel(), y_vals.ravel()])
# Reshape the output array
output = output.reshape(x_vals.shape)
# Create a plot
plt.figure()
# Choose a color scheme for the plot
# Overlay the training points on the plot
plt.scatter(X[:, 0], X[:, 1], c=y, s=75,edgecolors="black", linewidth=1, cmap=plt.cm.Paired)
# Specify the boundaries of the plot
plt.xlim(x_vals.min(), x_vals.max())
plt.ylim(y_vals.min(), y_vals.max())
# Specify the ticks on the X and Y axes
plt.xticks((np.arange(int(X[:, 0].min() -1), int(X[:, 0].max() + 1), 1.0)))
plt.yticks((np.arange(int(X[:, 1].min() -1), int(X[:, 1].max() + 1), 1.0)))
plt.show()
該函數將分類器對象,輸入數據和標籤作為輸入參數來創建函數定義,然後定義了將在我們的網格中使用的X和Y方向的最小值和最大值。接著,定義網格的步長並使用最小值和最大值創建網格。這裡的網格可以理解為一系列採樣點,用於評估函數的值,以便我們可以看到類的邊界。再在網格上的所有點上運行分類器,得到計算結果。最後,創建圖形,選擇配色方案,並覆蓋所有點,使用最小值和最大值指定圖的邊界,添加刻度線並顯示圖形。結果如下:
如果在下面一行中將C的值更改為100,
classifier =linear_model.LogisticRegression(solver="liblinear", C=100)
則會看到邊界變得更加準確:
這裡的原因是C對錯誤分類施加了一定的懲罰,所以該演算法對訓練數據擬合更好。不過使用這個參數應該小心,因為如果增加太多,它會過擬合訓練數據,不會有很好的泛化能力。
6樸素貝葉斯分類器
樸素貝葉斯是一種基於貝葉斯定理構建分類器的技術。貝葉斯定理根據與此事件相關的不同條件描述事件發生的概率。給定一組特徵向量和對應類標籤來構建一個樸素貝葉斯分類器。假設的數據滿足獨立同分布假設,即樸素貝葉斯分類器的樸素條件。
給定類變數,我們可以看到給定特徵如何影響,而不管它對其他特徵的影響如何。例如,如果一隻動物被發現,它可能被認為是獵豹,有四條腿,有一條尾巴,運行速度約為70英里/小時。樸素貝葉斯分類器認為每個特徵都對結果有獨立貢獻。結果是指這種動物是獵豹的概率。我們不關心皮膚圖案,腿的數量,尾巴的存在和移動速度之間可能存在的相關性。我們來看看如何構建一個樸素貝葉斯分類器。
導入下列軟體包:
import numpy as np
from sklearn.naive_bayesimport GaussianNB
from sklearn importcross_validation
下面載入數據,構建樸素貝葉斯分類器,並訓練模型,預測數據,計算預測精度,顯示分類器:
# Input file containingdata
input_file ="data_multivar_nb.txt"
# Load data from inputfile
data =np.loadtxt(input_file, delimiter=",")
X, y = data[:, :-1],data[:, -1]
# Create Naive Bayesclassifier
classifier =GaussianNB()
# Train the classifier
classifier.fit(X, y)
# Predict the values fortraining data
y_pred =classifier.predict(X)
# Compute accuracy
accuracy = 100.0 * (y ==y_pred).sum() / X.shape[0]
print("Accuracy ofNaive Bayes classifier =", round(accuracy, 2), "%")
# Visualize theperformance of the classifier
visualize_classifier(classifier,X, y)
運行上述代碼,得到如下結果和圖像:
Accuracy of Naive Bayesclassifier = 99.75 %
對數據進行交叉驗證,劃分訓練數據和測試數據,測試預測精度,繪製預測效果:
# Cross validation
# Split data intotraining and test data
X_train, X_test,y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.2, random_state=3)
classifier_new =GaussianNB()
classifier_new.fit(X_train,y_train)
y_test_pred =classifier_new.predict(X_test)
# compute accuracy ofthe classifier
accuracy = 100.0 *(y_test == y_test_pred).sum() / X_test.shape[0]
print("Accuracy ofthe new classifier =", round(accuracy, 2), "%")
# Visualize theperformance of the classifier
visualize_classifier(classifier_new,X_test, y_test)
運行上面程序,得到如下結果:
Accuracy of the newclassifier = 100.0 %
根據訓練的分類器,計算精度、準確率、召回率和F1分數。
# Scoring functions
num_folds = 3
accuracy_values =cross_validation.cross_val_score(classifier,
X, y, scoring="accuracy", cv=num_folds)
print("Accuracy:" + str(round(100*accuracy_values.mean(), 2)) + "%")
precision_values =cross_validation.cross_val_score(classifier,
X, y, scoring="precision_weighted",cv=num_folds)
print("Precision:" + str(round(100*precision_values.mean(), 2)) + "%")
recall_values =cross_validation.cross_val_score(classifier,
X, y, scoring="recall_weighted",cv=num_folds)
print("Recall:" + str(round(100*recall_values.mean(), 2)) + "%")
f1_values =cross_validation.cross_val_score(classifier,
X, y, scoring="f1_weighted",cv=num_folds)
print("F1: " +str(round(100*f1_values.mean(), 2)) + "%")
運行上面程序,得到如下結果:
Accuracy: 99.75%
Precision: 99.76%
Recall: 99.75%
F1: 99.75%
7混淆矩陣
混淆矩陣是用來描述分類器性能的圖形或表。它通常由已知的真實數據集的測試數據集中計算得到。將每個類與其他類進行比較,看看有多少個樣本被錯誤分類。在這個表的構建過程中,會涉及到機器學習領域中非常重要的幾個關鍵度量。讓我們考慮一個二類分類的情況,輸出是或1:
l真正例:預測為1的樣本,真實數據也是1。
l真反例:預測為的樣本,真實數據也是。
l假正例:預測為1的樣本,但真實數據為。也被稱為I型誤差。
l假反例:預測為的樣本,但真實數據為1。也被稱為II型誤差。
根據問題,我們可能不得不優化我們的演算法以減少誤報率或漏報率。例如,在一個生物識別系統,避免誤報是非常重要的,因為錯誤的人可能會接觸到敏感信息。
如何創建一個混淆矩陣?首先,導入下列軟體包:
import numpy as np
import matplotlib.pyplotas plt
from sklearn.metricsimport confusion_matrix
from sklearn.metricsimport classification_report
然後定義真實標籤和預測標籤:
# Define sample labels
true_labels = [2, 0, 0,2, 4, 4, 1, 0, 3, 3, 3]
pred_labels = [2, 1, 0,2, 4, 3, 1, 0, 1, 3, 3]
根據標籤創建混淆矩陣:
# Create confusionmatrix
confusion_mat =confusion_matrix(true_labels, pred_labels)
可視化混淆矩陣:
# Visualize confusionmatrix
plt.title("Confusionmatrix")
plt.colorbar()
ticks = np.arange(5)
plt.xticks(ticks, ticks)
plt.yticks(ticks, ticks)
plt.ylabel("Truelabels")
plt.xlabel("Predictedlabels")
plt.show()
運行程序,結果如下:
同時,輸出計算報告:
# Classification report
targets = ["Class-0","Class-1", "Class-2", "Class-3", "Class-4"]
print("
",classification_report(true_labels, pred_labels, target_names=targets))
執行程序,結果如下:
precision recall f1-score support
Class-0 1.00 0.67 0.80 3
Class-1 0.33 1.00 0.50 1
Class-2 1.00 1.00 1.00 2
Class-3 0.67 0.67 0.67 3
Class-4 1.00 0.50 0.67 2
avg / total 0.85 0.73 0.75 11
8支持向量機
支持向量機(SVM)是使用類之間的分離超平面定義的分類器。這個超平面可以理解為一條線的無限維版本。給定標記的訓練數據和二類分類問題,SVM找到將訓練數據分成兩類的最優超平面。該分類器可以很容易地擴展到N類的問題。
考慮一個具有兩類點的二維情況。鑒於它是2D的,只需要處理2D平面中的點和線。這比在高維空間中的矢量和超平面更容易可視化。當然,這是SVM問題的簡化版本。在將其應用於高維數據之前,了解它並將其可視化是非常重要的。
考慮下圖:
給定兩類點,要求找到最優超平面來分離兩個類。如何定義最優?圖中,你可以繪製許多不同的線來分離兩類點,但是實線是最好的超平面(分離線),因為它可以最大化每個點與分離線之間的距離。虛線上的點稱為支持向量。兩條虛線之間的垂直距離稱為最大間隔(margin)。
例:使用支持向量機分類收入數據
下面將構建一個支持向量機分類器,根據14個屬性來預測給定人的收入。目標是看每年的收入高於或低於5萬美元,這是一個二元分類問題。數據為人口普查收入數據集https://archive.ics.uci.edu/ml/datasets/Census+Income。在這個數據集中要注意的一點是,每個數據點是字和數字的混合體。我們不能使用原始格式的數據,因為演算法不知道如何處理單詞。我們無法使用標籤編碼器轉換所有內容,因為數字數據很有價值。因此,需要使用標籤編碼器和原始數值數據的組合來構建有效的分類器。
導入下列軟體包:
import numpy as np
from sklearn importpreprocessing
from sklearn.svm importLinearSVC
from sklearn.multiclassimport OneVsOneClassifier
from sklearn importcross_validation
載入數據:
# Input file containingdata
input_file ="income_data.txt"
# Read the data
X = []
y = []
count_class1 = 0
count_class2 = 0
max_datapoints = 25000
將數據轉化為分類問題:
with open(input_file,"r") as f:
for line in f.readlines():
if count_class1 >= max_datapointsand count_class2 >= max_datapoints:
break
if "?" in line:
continue
data = line[:-1].split(", ")
if data[-1] == "
X.append(data)
count_class1 += 1
if data[-1] == ">50K" andcount_class2
X.append(data)
count_class2 += 1
# Convert to numpy array
X = np.array(X)
將字元數據轉化為數值數據:
# Convert string data tonumerical data
label_encoder = []
X_encoded =np.empty(X.shape)
for i,item inenumerate(X[0]):
if item.isdigit():
X_encoded[:, i] = X[:, i]
else:
label_encoder.append(preprocessing.LabelEncoder())
X_encoded[:, i] =label_encoder[-1].fit_transform(X[:, i])
X = X_encoded[:,:-1].astype(int)
y = X_encoded[:,-1].astype(int)
創建支持向量機並訓練之:
# Create SVM classifier
classifier =OneVsOneClassifier(LinearSVC(random_state=0))
# Train the classifier
classifier.fit(X, y)
劃分訓練集和測試集,訓練和測試模型,輸出測試F1分數:
# Cross validation
X_train, X_test,y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.2,random_state=5)
classifier =OneVsOneClassifier(LinearSVC(random_state=0))
classifier.fit(X_train,y_train)
y_test_pred =classifier.predict(X_test)
# Compute the F1 scoreof the SVM classifier
f1 =cross_validation.cross_val_score(classifier, X, y, scoring="f1_weighted", cv=3)
print("F1 score:" + str(round(100*f1.mean(), 2)) + "%")
給定一個測試點,預測收入結果:
# Predict output for atest datapoint
input_data = ["37","Private", "215646", "HS-grad", "9", "Never-married", "Handlers-cleaners","Not-in-family", "White", "Male", "0", "0", "40", "United-States"]
# Encode test datapoint
input_data_encoded =[-1] * len(input_data)
count = 0
for i, item inenumerate(input_data):
ifitem.isdigit():
input_data_encoded[i] =int(input_data[i])
else:
input_data_encoded[i] =int(label_encoder[count].transform([input_data[i]]))
count += 1
input_data_encoded =np.array(input_data_encoded)
# Run classifier onencoded datapoint and print output
predicted_class =classifier.predict(input_data_encoded.reshape(1,-1))
print("The predictresult is:")
print(label_encoder[-1].inverse_transform(predicted_class)[0])
運行代碼,則需要幾秒鐘來訓練分類器。完成後,您將在終端上看到以下內容:
F1 score: 70.82%
還將看到測試數據點的輸出:
The predict result is:
如果檢查該數據點中的值,則會發現它與小於50K類的數據點緊密對應。可以使用各種不同的內核來改變分類器的性能(F1分數、精度或召回),並嘗試多個參數組合。
9回歸
回歸是估計輸入和輸出變數之間關係的過程。需要注意的是輸出變數不同於分類問題,其數值不再是屬於一個固定的可能集合,而是連續實數。因此,有無限的可能性。
在回歸中,假定輸出變數取決於輸入變數,則要研究的是它們之間的相關性。因此,輸入變數稱為獨立變數,也稱為預測變數;輸出變數稱為相關變數,也稱為標準變數。輸入變數不必彼此獨立,很多情況下輸入變數之間是存在相關性的。
回歸分析有助於我們了解在保持其他輸入變數不變時改變某些輸入變數,輸出變數的值如何變化。在線性回歸中,假設輸入和輸出之間的關係是線性的,通過施加該約束,可以使模型更加快速高效。
有時,線性回歸不足以解釋輸入和輸出之間的關係。因此,我們會使用多項式回歸,即使用多項式來解釋輸入和輸出之間的關係,在計算上更加複雜,但是具有更高的準確性。實際中,根據問題需要,可採用不同形式的回歸模型來建模關係。回歸常用於預測價格、經濟走勢、變化等等。
單變數回歸
導入相關軟體包:
import numpy as np
from sklearn importlinear_model
import sklearn.metricsas sm
import matplotlib.pyplotas plt
然後,載入數據,並按照80%和20%的比例劃分訓練集合測試集:
# Input file containingdata
input_file ="../data/data_singlevar_regr.txt"
# Read data
data =np.loadtxt(input_file, delimiter=",")
X, y = data[:, :-1],data[:, -1]
# Train and test split
num_training = int(0.8 *len(X))
num_test = len(X) -num_training
# Training data
X_train, y_train =X[:num_training], y[:num_training]
# Test data
X_test, y_test =X[num_training:], y[num_training:]
其中,數據集中特徵間以逗號分隔,一個數據占單獨一行。
接下來,創建線性回歸器,並根據訓練數據訓練模型,再對測試數據進行測試:
# Create linearregressor object
regressor =linear_model.LinearRegression()
# Train the model usingthe training sets
regressor.fit(X_train, y_train)
# Predict the output
y_test_pred =regressor.predict(X_test)
然後,對結果進行輸出:
# Plot outputs
plt.scatter(X_test,y_test, color="green")
plt.plot(X_test,y_test_pred, color="black", linewidth=4)
plt.xticks(())
plt.yticks(())
plt.show()
# Compute performancemetrics
print("Linearregressor performance:")
print("Meanabsolute error =", round(sm.mean_absolute_error(y_test, y_test_pred), 2))
print("Mean squarederror =", round(sm.mean_squared_error(y_test, y_test_pred), 2))
print("Medianabsolute error =", round(sm.median_absolute_error(y_test, y_test_pred),2))
print("Explainvariance score =", round(sm.explained_variance_score(y_test, y_test_pred),2))
print("R2 score=", round(sm.r2_score(y_test, y_test_pred), 2))
運行程序,得到如下結果:
其中直線為預測的線性模型,綠點為實際的測試數據點。相關量化評測結果如下:
Linear regressorperformance:
Mean absolute error =0.59
Mean squared error =0.49
Median absolute error =0.51
Explain variance score =0.86
R2 score = 0.86
對於學習得到的模型可使用pickle先存儲起來,後續使用時只需載入模型進行預測:
import pickle
# Model persistence
output_model_file ="model.pkl"
# Save the model
withopen(output_model_file, "wb") as f:
pickle.dump(regressor, f)
# Load the model
withopen(output_model_file, "rb") as f:
regressor_model = pickle.load(f)
# Perform prediction ontest data
y_test_pred_new =regressor_model.predict(X_test)
print("
New meanabsolute error =", round(sm.mean_absolute_error(y_test, y_test_pred_new),2))
運行程序,得到如下結果:
New mean absolute error = 0.59
多變數回歸
多變數回歸與單變數類似,只是輸入數據的維度為多維,具體代碼如下:
import numpy as np
from sklearn import linear_model
import sklearn.metricsas sm
fromsklearn.preprocessing import PolynomialFeatures
# Input file containingdata
input_file ="../data/data_multivar_regr.txt"
# Load the data from theinput file
data =np.loadtxt(input_file, delimiter=",")
X, y = data[:, :-1],data[:, -1]
# Split data intotraining and testing
num_training = int(0.8 *len(X))
num_test = len(X) -num_training
# Training data
X_train, y_train =X[:num_training], y[:num_training]
# Test data
X_test, y_test =X[num_training:], y[num_training:]
# Create the linearregressor model
linear_regressor =linear_model.LinearRegression()
# Train the model usingthe training sets
linear_regressor.fit(X_train,y_train)
# Predict the output
y_test_pred =linear_regressor.predict(X_test)
# Measure performance
print("LinearRegressor performance:")
print("Meanabsolute error =", round(sm.mean_absolute_error(y_test, y_test_pred), 2))
print("Mean squarederror =", round(sm.mean_squared_error(y_test, y_test_pred), 2))
print("Medianabsolute error =", round(sm.median_absolute_error(y_test, y_test_pred),2))
print("Explainedvariance score =", round(sm.explained_variance_score(y_test, y_test_pred),2))
print("R2 score=", round(sm.r2_score(y_test, y_test_pred), 2))
輸出結果如下:
Linear Regressorperformance:
Mean absolute error =3.58
Mean squared error =20.31
Median absolute error =2.99
Explained variance score= 0.86
R2 score = 0.86
創建一個自由度為10的多項式回歸器,在訓練數據上訓練回歸器。
# Polynomial regression
polynomial =PolynomialFeatures(degree=10)
X_train_transformed =polynomial.fit_transform(X_train)
datapoint = [[7.75,6.35, 5.56]]
poly_datapoint =polynomial.fit_transform(datapoint)
仔細觀察,發現該點與文件中第11行數據([7.66,6.29,5.66])非常接近,因此好的預測結果應該接近於41.35。下面創建回歸器並訓練模型,最後輸出結果:
poly_linear_model =linear_model.LinearRegression()
poly_linear_model.fit(X_train_transformed,y_train)
print("
Linearregression:
", linear_regressor.predict(datapoint))
print("
Polynomialregression:
", poly_linear_model.predict(poly_datapoint))
運行程序,得到如下結果:
Linear regression:
Polynomial regression:
10支持向量回歸機
本小節使用支持向量機概念構建一個回歸器估計房價,使用sklearn中由13個屬性定義的房價數據集,目標是根據這些屬性估算房價。
導入下列軟體包:
from sklearn importdatasets
from sklearn.svm importSVR
from sklearn.metricsimport mean_squared_error, explained_variance_score
from sklearn.utilsimport shuffle
載入房價數據:
# Load housing data
data =datasets.load_boston()
為了保證分析是無偏的,打亂數據的順序:
# Shuffle the data
X, y =shuffle(data.data, data.target, random_state=7)
按照80%和20%的比例劃分訓練集合測試集:
# Split the data intotraining and testing datasets
num_training = int(0.8 *len(X))
X_train, y_train =X[:num_training], y[:num_training]
X_test, y_test =X[num_training:], y[num_training:]
創建一個線性核支持向量回歸機,並根據訓練數據訓練之:
# Create Support VectorRegression model
sv_regressor =SVR(kernel="linear", C=1.0, epsilon=0.1)
# Train Support VectorRegressor
sv_regressor.fit(X_train,y_train)
該回歸其參數C為懲罰因子。不適當的因子可能會導致過擬合,影響模型的泛化能力。參數epsilon指定閾值,若預測值與真實值差異小於閾值,則不施加懲罰。
然後對測試數據進行評測,輸出均方誤差和方差:
# Evaluate performanceof Support Vector Regressor
y_test_pred =sv_regressor.predict(X_test)
mse =mean_squared_error(y_test, y_test_pred)
evs =explained_variance_score(y_test, y_test_pred)
print("
####Performance ####")
print("Mean squarederror =", round(mse, 2))
print("Explainedvariance score =", round(evs, 2))
輸出的評測結果如下:
#### Performance ####
Mean squared error =15.41
Explained variance score= 0.82
使用新的測試數據進行預測:
# Test the regressor ontest datapoint
test_data = [3.7, 0,18.4, 1, 0.87, 5.95, 91, 2.5052, 26, 666, 20.2, 351.34, 15.27]
print("
Predictedprice:", sv_regressor.predict([test_data])[0])
輸出測試結果如下:
總結
本節中,我們學習了有監督和無監督學習之間的區別。討論了數據分類問題及其解決方法。了解了如何使用各種方法預處理數據。還學習了標籤編碼以及如何構建標籤編碼器。討論了Logistic回歸,並建立了logistic回歸分類器。理解了樸素貝葉斯分類器是什麼,並學習了如何構建它。還學習了如何建立混淆矩陣。最後討論了支持向量機,並了解如何構建一個支持向量機分類器和支持向量回歸器。
參考文獻
[1]普拉提克·喬希(Prateek Joshi),人工智慧:Python實現(影印版)(英文版),東南大學出版社, 2017.
PS:本節內容由陸工大碩士研究生張洋碩翻譯,王一鳴校對。
TAG:知不知者 |