機器學習 | 鳶尾花分類專案實戰
前言:本系列部落格參考於 《機器學習演算法導論》和《Python機器學習》
如有侵權,敬請諒解。本書儘量用總結性的語言重述本書內容,避免侵權。
上一篇已經介紹了感知器演算法規則,並且用 Python 語言實現了。現在我們應用感知器學習規則進行鳶尾花分類實驗。
\[QAQ \]
測試資料我們從鳶尾花資料集中挑選出了山鳶尾(Setosa)和變色鳶尾(Versicolor)兩種花的資訊作為測試資料。雖然感知器並不將資料樣本特徵的數量限定為兩個,但出於視覺化的原因,我們只考慮資料集中萼片長度(sepal length)和花瓣長度(petal length)這兩個特徵。同時,選擇山鳶尾和變色鳶尾也是出於實踐需要的考慮。不過,感知器演算法可以擴充套件到多類別的分類器應用中,比如通過一對多技術。
注:一對多技術也稱為一對其他技術,是一種將二分類技術擴充到多類別分類任務上的一種技術。
我們可以使用 \(QvA\) 針對每個類別訓練一個分類器,其中分類器所對應類別樣本為正類別,其他所有分類器的樣本為負類別。
當應用與新資料樣本識別時,我們可以藉助於分類器 \(\phi(z)\) ,其中m為類標數量,並將相關度最高的類標賦給待識別樣本。對於感知器來說,就是最大淨輸入值絕對值對應的類標。
1、載入訓練資料
使用 pandas
庫直接從 \(UCI\) 機器學習庫中將鳶尾花資料集轉換為 DataFrame
物件並載入到記憶體中,並使用 tail
方法現實部分資料資訊.
import pandas as pd df = pd.read_csv( "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", header=None) # df = pd.read_csv("iris.data", header=None) # 輸出最後20行的資料,並觀察資料結構 萼片長度(sepal length),萼片寬度(), # 花瓣長度(petal length),花瓣寬度,種類 print(df.tail(n=20)) print(df.shape)
2、繪製訓練資料
我們從鳶尾花資料集中提取前 \(100\) 個類標,其中分別包含 \(50\) 個山鳶尾類標和 \(50\) 個變色鳶尾類標,並將這些類標用兩個整數值來替代:\(1\) 代表變色鳶尾,\(-1\) 代表山鳶尾,同時把 pandas DataFrame
產生的對應的整數類標賦值給 Numpy
的向量 \(y\)
類似的,我們提取這 \(100\) 個訓練樣本的第一個特徵列(萼片長度)和第三個特徵列(花瓣長度),並賦值給屬性矩陣 \(X\),這樣我們就可以用二維散點圖對這些資料進行可視化了。
# 0到100行,第5列 y = df.iloc[0:100, 4].values # 將target值轉數字化 Iris-setosa為-1,否則值為1 y = np.where(y == "Iris-setosa", -1, 1) # 取出0到100行,第1,第三列的值 x = df.iloc[0:100, [0, 2]].values """ 鳶尾花散點圖 """ # scatter繪製點圖 plt.scatter(x[0:50, 0], x[0:50, 1], color="red", marker="o", label="setosa") plt.scatter(x[50:100, 0], x[50:100, 1], color="blue", marker="x", label="versicolor") # 防止中文亂碼 下面分別是windows系統,mac系統解決中文亂碼方案 zh = mat.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc') plt.title("鳶尾花散點圖", fontproperties=zh) plt.xlabel(u"花瓣長度", fontproperties=zh) plt.ylabel(u"萼片長度", fontproperties=zh) plt.legend(loc="upper left") plt.show()
3、訓練資料
現在我們可以利用抽取出的鳶尾花資料子集來訓練感知器了。同時,我們還將繪製每次迭代的錯誤分類數量的折線圖,以檢驗演算法是否收斂並找到可以分開兩種型別鳶尾花的決策邊界。
訓練程式碼:
from perceptron import Perceptron
import matplotlib.pyplot as plt
import matplotlib as mat
import pandas as pd
import numpy as np
"""
訓練模型並且記錄錯誤次數,觀察錯誤次數的變化
"""
print(__doc__)
# 載入鳶尾花資料
df = pd.read_csv(
"https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data",
header=None)
# df = pd.read_csv("iris.data", header=None)
# 資料真實值
y = df.iloc[0:100, 4].values
y = np.where(y == "Iris-setosa", -1, 1)
x = df.iloc[0:100, [0, 2]].values
"""
誤差數折線圖
@:param eta: 0.1 學習速率
@:param n_iter:0.1 迭代次數
"""
ppn = Perceptron(eta=0.1, n_iter=10)
ppn.fit(x, y)
# plot繪製折線圖
plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker="o")
# 防止中文亂碼
zhfont1 = mat.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
plt.xlabel("迭代次數(n_iter)", fontproperties=zhfont1)
plt.ylabel("錯誤分類次數(error_number)", fontproperties=zhfont1)
plt.show()
上面的程式碼繪製了每輪迭代的錯誤次數,從圖可以看出,在第 \(6\) 輪迭代之後的出錯次數已經降為 \(0\)(收斂),並且具備了對訓練樣本及進行正確分類的能力。
4、決策邊界視覺化
以下程式碼是對鳶尾花花萼長度、花瓣長度進行視覺化及分類
from os import makedirs
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from My_Perceptron import Perceptron
import matplotlib.pyplot as plt
import matplotlib as mat
import pandas as pd
iris = datasets.load_iris()
X = iris["data"][:, (0, 1)]
y = 2 * (iris["target"] == 0).astype(np.int64) - 1
X_train, X_test, y_train, y_test = train_test_split(X,
y,
test_size=0.4,
random_state=5)
model = Perceptron()
model.fit(X_train, y_train)
model.predict(X_test)
plt.figure(2)
plt.axis([4, 8, 1, 5])
plt.plot(X_train[:, 0][y_train == 1], X_train[:, 1][y_train == 1], "bs", ms=3)
plt.plot(X_train[:, 0][y_train == -1],
X_train[:, 1][y_train == -1],
"yo",
ms=3)
x0 = np.linspace(4, 8, 200)
w = model.w
b = model.b
line = -w[0] / w[1] * x0 - b / w[1]
plt.plot(x0, line)
# 防止中文亂碼 下面分別是windows系統,mac系統解決中文亂碼方案
zh = mat.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
plt.title("鳶尾花散點圖", fontproperties=zh)
plt.xlabel(u"花瓣長度", fontproperties=zh)
plt.ylabel(u"萼片長度", fontproperties=zh)
# plt.legend(loc="upper left")
plt.show()
import perceptron as pp
import pandas as pd
import matplotlib as mat
from matplotlib.colors import ListedColormap
import numpy as np
import matplotlib.pyplot as plt
def plot_decision_regions(x, y, classifier, resolution=0.2):
"""
二維資料集決策邊界視覺化
:parameter
-----------------------------
:param self: 將鳶尾花花萼長度、花瓣長度進行視覺化及分類
:param x: list 被分類的樣本
:param y: list 樣本對應的真實分類
:param classifier: method 分類器:感知器
:param resolution:
:return:
-----------------------------
"""
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
# y去重之後的種類
listedColormap = ListedColormap(colors[:len(np.unique(y))])
# 花萼長度最小值-1,最大值+1
x1_min, x1_max = x[:, 0].min() - 1, x[:, 0].max() + 1
# 花瓣長度最小值-1,最大值+1
x2_min, x2_max = x[:, 1].min() - 1, x[:, 1].max() + 1
# 將最大值,最小值向量生成二維陣列xx1,xx2
# np.arange(x1_min, x1_max, resolution) 最小值最大值中間,步長為resolution
new_x1 = np.arange(x1_min, x1_max, resolution)
new_x2 = np.arange(x2_min, x2_max, resolution)
xx1, xx2 = np.meshgrid(new_x1, new_x2)
# 預測值
# z = classifier.predict([xx1, xx2])
z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
z = z.reshape(xx1.shape)
plt.contourf(xx1, xx2, z, alpha=0.4, camp=listedColormap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
for idx, c1 in enumerate(np.unique(y)):
plt.scatter(x=x[y == c1, 0],
y=x[y == c1, 1],
alpha=0.8,
c=listedColormap(idx),
marker=markers[idx],
label=c1)
df = pd.read_csv(
"https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data",
header=None)
# 0到100行,第5列
y = df.iloc[0:100, 4].values
# 將target值轉數字化 Iris-setosa為-1,否則值為1,相當於啟用函式-在此處表現為分段函式
y = np.where(y == "Iris-setosa", -1, 1)
# 取出0到100行,第1,第三列的值
x = df.iloc[0:100, [0, 2]].values
ppn = pp.Perceptron(eta=0.1, n_iter=10)
ppn.fit(x, y)
plot_decision_regions(x, y, classifier=ppn)
# 防止中文亂碼
zhfont1 = mat.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
plt.title("鳶尾花花瓣、花萼邊界分割", fontproperties=zhfont1)
plt.xlabel("花瓣長度 [cm]", fontproperties=zhfont1)
plt.ylabel("花萼長度 [cm]", fontproperties=zhfont1)
plt.legend(loc="uper left")
plt.show()
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。