機器學習 | 鳶尾花分類項目實戰


前言:本系列博客參考於 《機器學習算法導論》和《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()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM