文章目錄
0. 原理
待更
1. 應用-Iris數據集
來源於《Python機器學習基礎教程》一書,機器學習之旅從鳶尾花開始~
注意:python中機器學習數據集結構:
feature | target |
---|---|
X1,…,Xn | y |
data | target |
X | y |
scikit-learn 中的數據通常用大寫的X 表示,而標籤用小寫的y 表示。這是來源於f(x)=y ,其中x 是函數的輸入,y 是輸出。大寫的X是因爲數據是一個二維數組(矩陣),小寫的y 是因爲目標是一個一維數組(向量),這也是數學中的約定。
導入包並加載數據
import numpy as np
import pandas as pd
import seaborn as sns # 美化繪圖
import sklearn
from sklearn.datasets import load_iris # 導入數據集
iris_dataset = load_iris() # 加載後的數據是Bunch對象,類似於字典
查看數據
print("Keys of iris_dataset:\n{}".format(iris_dataset.keys()))
# 其中DESCR是數據集的說明
Keys of iris_dataset:
dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename'])
print(iris_dataset['DESCR']) # print帶格式,直接輸出沒有格式
著名的鳶尾花數據集, 請注意,它與R中的相同,但與UCI中的不同
機器學習存儲庫,其中有兩個錯誤的數據點。
print(iris_dataset['target_names']) # 類別名
print(iris_dataset['feature_names']) # 特徵名
print(type(iris_dataset['data'])) # 數據結構
print(iris_dataset['data'].shape) # 維度
print(iris_dataset['data'][:5]) # 數據前五行
print(type(iris_dataset['target'])) # target's type
print(iris_dataset['target'].shape) # target's shape
iris_dataset['target'] # 0,1,2
iris_dataset['target_names']
# array(['setosa', 'versicolor', 'virginica'], dtype='<U10'),對應0,1,2
數據拆分爲訓練集與測試集
scikit-learn 中的train_test_split 函數可以隨機打亂數據集並進行拆分。默認將75% 的行數據及對應標籤作爲訓練集,剩下25% 的數據及其標籤作爲測試集。使用25% 的數據作爲測試集是很好的經驗法則。
from sklearn.model_selection import train_test_split
X, y = iris_dataset['data'], iris_dataset['target']
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
print(X_train.shape) # (112, 4)
- 爲什麼要打亂順序?如果只將後25%用於測試,則測試集都來自第3種花,不合理,確保test中含有所有類別的數據
- 爲什麼指定隨機數種子?爲了確保多次運行同一函數能夠得到相同的輸出
# Split arrays or matrices into random train and test subsets
?train_test_split
X_train, X_test, y_train, y_test = train_test_split(data_X,data_y,…) : 返回4個array
- test_size : if float,between 0.0 and 1.0,測試集應占的比例,默認0.25;if int,表示測試集中的樣本數
- random_state : If int, random_state is the seed used by the random number generator;隨機數種子
- shuffle :(default=True):在拆分前是否隨機打亂數據順序
注:詳情與示例見docstring
觀察數據-可視化
散點圖,將一個特徵作爲x 軸,另一個特徵作爲y 軸,將每一個數據點繪製爲圖上的一個點,一次只能繪製兩個特徵,對多於3 個特徵的數據集作圖,繪製散點圖矩陣。
散點圖矩陣無法同時顯示所有特徵之間的關係,只能兩兩查看,所以這種可視化方法可能無法展示數據的某些有趣內容。
建議使用seaborn繪製
# 先轉換爲dataframe,然後使用pandas.scatter_matrix(),對角線是每個特徵的直方圖或密度圖
df = pd.DataFrame(X_train,columns=iris_dataset['feature_names'])
# 創建散點圖矩陣,按y_train着色(一列標籤)。因爲X_train和y_train一一對應
grr = pd.plotting.scatter_matrix(df,c=y_train,figsize=(10,10),marker='.',hist_kwds={'bins':20},s=60,alpha=0.8)
pandas自帶繪圖函數pd.plotting.scatter_matrix(frame)
可選參數:(詳見docstring)
- diagonal:必須且只能在{‘hist’, ‘kde’}中選擇1個,’hist’表示直方圖,’kde’表示核密度估計(Kernel Density Estimation),該參數是scatter_matrix函數的關鍵參數。
- hist_kwds:與hist相關的字典參數
- c:顏色
對於散點圖矩陣,seaborn包畫圖更美觀。
sns繪製散點圖矩陣所需的數據結構是X與y在一起的一個df。
使用詳情參見docstring。
y_train_se = pd.Series(y_train) # se可以自動變換類型,array不可以
y_train_se[y_train_se == 0] = 'setosa' # 方便圖例生成
y_train_se[y_train_se == 1] = 'versicolor'
y_train_se[y_train_se == 2] = 'virginica'
df['class'] = y_train_se # sns繪製散點圖矩陣所需的數據結構是X與y在一起的一個df
sns.pairplot(df,plot_kws={'alpha':0.8},hue='class') # hue爲df中一列的列名,爲不同的點標記顏色,該列的值爲圖例,按類別標籤着色
參考:
https://blog.csdn.net/zyb228/article/details/101940096/
https://www.jianshu.com/p/6e18d21a4cad
kNN-model
- k近鄰分類器:構建此模型只需要保存訓練集即可。要對一個新的數據點做出預測,算法會在訓練集中尋找與這個新數據點距離最近的數據點,然後將找到的數據點的標籤賦值給這個新數據點。
- k的含義是,我們可以考慮訓練集中與新數據點最近的任意k個鄰居,用這些鄰居中數量最多的類別做出預測。
- scikit-learn 中所有的機器學習模型都在各自的類中實現。k 近鄰分類算法是在neighbors 模塊的KNeighborsClassifier 類中實現的。需要將這個類實例化爲一個對象,然後才能使用這個模型。這時我們需要設置模型的參數。
- KNeighborsClassifier 最重要的參數就是鄰居的數目
docstring的示例:
?KNeighborsClassifier
Examples
--------
>>> X = [[0], [1], [2], [3]]
>>> y = [0, 0, 1, 1]
>>> from sklearn.neighbors import KNeighborsClassifier
>>> neigh = KNeighborsClassifier(n_neighbors=3)
>>> neigh.fit(X, y) # doctest: +ELLIPSIS
KNeighborsClassifier(...)
>>> print(neigh.predict([[1.1]]))
[0]
>>> print(neigh.predict_proba([[0.9]]))
[[0.66666667 0.33333333]]
應用:
from sklearn.neighbors import KNeighborsClassifier # knn也可用於迴歸,是KNeighborsRegression
knn = KNeighborsClassifier(n_neighbors=1) # 設置具體參數來實例化
knn 對象對算法進行了封裝,既包括用訓練數據構建模型的算法,也包括對新數據點進行預測的算法。它還包括算法從訓練數據中提取的信息。
對KNeighborsClassifier 來說,裏面只保存了訓練集。
想要基於訓練集來構建模型,需要調用knn 對象的fit 方法,輸入參數爲X_train 和y_train,二者都是NumPy 數組,前者包含訓練數據,後者包含相應的訓練標籤:
knn.fit(X_train,y_train) # fit 方法返回的是knn 對象本身並做原處修改,因此得到分類器的字符串表示。從中可以看出構建模型時用到的參數。
# 模型都有很多參數,但多用於速度優化或非常特殊的用途。
評估模型-使用測試集,進行結果對比
可以通過計算精度(accuracy)來衡量模型的優劣,精度就是品種預測正確的花所佔的比例:
# 得到測試集的預測值
y_pred = knn.predict(X_test)
y_pred # array([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1,0, 0, 2, 0, 0, 1, 1, 0, 2, 1, 0, 2, 2, 1, 0, 2])
# 與測試集的真實值比較得到精度
np.mean(y_pred == y_test) # 0,1之間算1的比例就是所有的平均值,等價於
knn.score(X_test,y_test) # 0.9736842105263158
?knn.score
Returns the mean accuracy on the given test data and labels.
進行預測
X_new = np.array([[5,2.9,1,0.2]]) # 一條新數據
print(X_new.shape) # (1, 4),二維數組的一行,因爲scikit-learn的輸入數據必須是二維數組。
prediction = knn.predict(X_new) # 預測
prediction # array([0]) ,類別是0
iris_dataset['target_names'][prediction] # array(['setosa'], dtype='<U10')
2. 模型複雜度和泛化能力之間的關係-乳腺癌數據集
from sklearn.datasets import load_breast_cancer
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
cancer = load_breast_cancer()
cancer.keys()
print(cancer.DESCR)
# 拆分訓練集與測試集
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state=66)
strtigy : array-like, 數據以分層方式拆分,並將其用作類標籤。按不同類別所佔比例拆分?並轉換爲0,1標籤?
## 記錄訓練集精度和測試集精度
n_max = 10
n_range = range(1,n_max+1) # 鄰居範圍
train_acc = np.zeros(n_max)
test_acc = np.zeros(n_max)
for i,n in enumerate(n_range):
knn = KNeighborsClassifier(n_neighbors=n)
knn.fit(X_train,y_train)
train_acc[i] = knn.score(X_train,y_train)
test_acc[i] = knn.score(X_test,y_test)
## 畫圖
plt.plot(n_range,train_acc,label='train acc')
plt.plot(n_range,test_acc,label='test_acc',linestyle='--')
plt.xlabel('n neighbors')
plt.ylabel('Accuracy')
plt.legend()
可以看出,更少的鄰居對應更復雜的模型,訓練集精度高,測試集精度低,最近鄰是過擬合。
泛化最佳性能在n=6時,測試集精度最高。
最差的性能約爲88% 的精度,這個結果仍然可以接受。
3. kNN迴歸
- 在使用多個近鄰進行時,預測結果爲這些鄰居的平均值。
- 評估模型:score 方法,對於迴歸問題,返回R2,即決定係數,是迴歸模型預測的優度度量,等於1 對應完美預測,等於0 對應常數模型,即總是預測訓練集響應(y_train)的平均值。R2越大擬合越好
from sklearn.neighbors import KNeighborsRegressor # kNN迴歸器
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 模型實例化,並將鄰居個數設爲3
reg = KNeighborsRegressor(n_neighbors=3)
# 利用訓練數據和訓練目標值來擬合模型
reg.fit(X_train, y_train)
# 預測結果
reg.predict(X_test)
# 評估模型
reg.score(X_test, y_test)