1. 程式人生 > >機器學習(三):感知器演算法實現鳶尾花分類專案實戰

機器學習(三):感知器演算法實現鳶尾花分類專案實戰

上一章我們已經介紹了感知器演算法規則,並且用python語言實現了。現在我們應用感知器學習規則進行鳶尾花分類實驗。

測試資料我們從鳶尾花資料集中挑選出了山鳶尾(Setosa)和變色鳶尾(Versicolor)兩種花的資訊作為測試資料。雖然感知器並不將資料樣本特徵的數量限定為兩個,但出於視覺化的原因,我們只考慮資料集中萼片長度(sepal length)和花瓣長度(petal length)這兩個特徵。同時,選擇山鳶尾和變色鳶尾也是出於實踐需要的考慮。不過,感知器演算法可以擴充套件到多類別的分類器應用中,比如通過一對多技術。

注:一對多技術也稱為一對其他技術,是一種將二分類技術擴充到多類別分類任務上的一種技術。
我們可以使用QvA針對每個類別訓練一個分類器,其中分類器所對應類別樣本為正類別,其他所有分類器的樣本為負類別。當應用與新資料樣本識別時,我們可以藉助於分類器

ϕ(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)
# 輸出最後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系統解決中文亂碼方案 # zhfont1 = mat.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc') zhfont1 = mat.font_manager.FontProperties(fname='/System/Library/Fonts/PingFang.ttc') plt.title("鳶尾花散點圖", fontproperties=zhfont1) plt.xlabel(u"花瓣長度", fontproperties=zhfont1) plt.ylabel(u"萼片長度", fontproperties=zhfont1) 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)

# 資料真實值
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、決策邊界視覺化

以下程式碼是對鳶尾花花萼長度、花瓣長度進行視覺化及分類

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()

這裡寫圖片描述

正如圖中看到的那樣,通過感知器學習得到的分類曲面可以完美地對訓練子集中的所有樣本進行分類。