機器學習練習三:Python實現多分類問題和前饋神經網絡

1.多分類邏輯迴歸問題

數據介紹:ex3data1中有5000個訓練實例。其中每一個訓練實例是一個20像素乘20像素灰度圖像的數字。每一個像素由一個浮點數表示,表示該位置的灰度強度。這個20x20的像素網格被「展開」成一個400維的向量。這些訓練示例中的每個都變成了數據矩陣X中的單行。這就獲得了一個5000×400矩陣X,其中每一行都是一個手寫數字圖像的訓練示例。數組

1.1 展現原始數據

數據集是在MATLAB的本機格式,因此要加載它在Python,咱們須要使用一個SciPy庫。bash

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from scipy.io import loadmat
# 加載數據
data = loadmat('ex3data1.mat')
X, y = data['X'], data['y']
複製代碼
  • 畫單張圖片

畫出圖片的函數:網絡

# 數據展現
def plot_fig():
    """ 原始數據可視化 """
    # 一個隨機數
    row = np.random.randint(0, 4999)
    # 取第row行,全部列
    fig_data = X[row:row + 1,:]  
    # 對於該數據集來講須要轉置一下才是正常的圖形
    fig_data = fig_data.reshape((20,20)).T
    # 繪圖
    fig, ax = plt.subplots(figsize=(1,1))
    # cmap=matplotlib.cm.binary:灰度顏色表
    ax.matshow(fig_data, cmap=matplotlib.cm.binary)
    # 去掉刻度線
    plt.xticks([])
    plt.yticks([])
    # 取真實y值
    y_true = y[row:row + 1,:][0][0]
    # 該數據集中0是用10來表示的
    if y_true == 10:
        y_true -= 10
    print("這個數應該是:{}".format(y_true) )
    plt.show()
複製代碼

運行結果: app

  • 畫100張圖片
def plot_100figs():
    """ 畫100幅圖 """
    # 隨機100個索引,不重複
    sample_list = np.random.choice(np.arange(X.shape[0]), 100, replace=False)
    # 從數據中取出這100個值
    sample_data = X[sample_list, :]
    # 畫圖, sharex,sharey:子圖共享x軸,y軸, ax_array:一個10*10的矩陣
    fig, ax_array = plt.subplots(nrows=10, ncols=10, sharex=True, sharey=True, figsize=(8, 8))
    # 畫子圖
    for r in range(10):
        for c in range(10):
            ax_array[r, c].matshow(sample_data[10 * r + c, :].reshape((20, 20)).T,
                             cmap=matplotlib.cm.binary)
    # 去掉刻度線
    plt.xticks([])
    plt.yticks([])
    plt.show()
複製代碼

np.random.choice(a,b,c):從第一個參數的範圍內抽取b個值,且不容許出現重複值。dom

運行結果:機器學習

1.2 定義sigmoid函數、損失函數和梯度降低函數

這裏所用的三個函數與二分類正則化邏輯迴歸相同,請見個人上一篇文章機器學習練習二:用Python實現邏輯迴歸函數

1.3 模型訓練

如今咱們已經定義了代價函數和梯度函數,是構建分類器的時候了。 對於這個任務,咱們有10個可能的類,而且因爲邏輯迴歸只能一次在2個類之間進行分類,咱們須要多類分類的策略。 在本練習中,咱們的任務是實現一對一全分類方法,其中具備k個不一樣類的標籤就有k個分類器,每一個分類器在「類別 i」和「不是 i」之間決定。 咱們將把分類器訓練包含在一個函數中,該函數計算10個分類器中的每一個分類器的最終權重,並將權重返回爲k *(n + 1)數組,其中n是樣本特徵值數量。post

# 使用 scipy.optimize.minimize 去尋找參數
import scipy.optimize as opt
def one_vs_all(X, y, k, lambd):
    """ 模型訓練 """
    rows = X.shape[0]
    params = X.shape[1]
    
    # theta是一個(k,n+1)的矩陣,k是分類數,n是樣本的特徵數量
    all_theta = np.zeros((k, params + 1))
    
    # 插入全1列x0
    X = np.insert(X, 0, values=np.ones(rows), axis=1)
    
    # 訓練
    for i in range(1, k + 1):
        # 其中的一組theta
        theta = np.zeros(params + 1)
        # 生成單個類別的二分類矩陣
        y_i = np.array([1 if label == i else 0 for label in y])
        y_i = np.reshape(y_i, (rows, 1))
        
        # 獲得使得全部樣本爲第i類損失最小的theta值
        fmin = opt.minimize(fun=cost, x0=theta, args=(X, y_i, lambd), method='TNC', jac=gradient)
        all_theta[i-1,:] = fmin.x
    
    return all_theta
複製代碼

這裏的for i in range(1, k + 1):之因此加1是爲了與目標值1,2,3...10相對應,而每個循環都是爲了計算使得全部樣本爲第i類的損失最小的theta值,最終獲得10分類的theta值。學習

1.4 計算準確率

咱們如今準備好最後一步,使用訓練完畢的分類器預測每一個圖像的標籤。 對於這一步,咱們將計算每一個類的類機率,對於每一個訓練樣本(使用固然的向量化代碼),並將輸出類標籤爲具備最高几率的類。ui

簡言之,須要將每一個樣本中機率最大的值找出來,其索引就是所預測的類。

# 獲取訓練集預測結果
def predict(all_theta, X):
    # y_predict_re = []
    # 插入全1列x0
    X = np.insert(X, 0, values=np.ones(X.shape[0]), axis=1)
    all_theta = np.mat(all_theta)
    # y_predict --> (5000,10)
    y_predict = np.array(sigmoid(X @ all_theta.T))
    """ for i in range(y_predict.shape[0]): for j in range(y_predict.shape[1]): if y_predict[i][j] == max(y_predict[i]): y_predict_re.append(j + 1) """
    # 按行取最大值索引
    y_predict_re = np.argmax(y_predict,axis=1) + 1
    return y_predict_re
複製代碼

np.argmax():按行取最大值索引,矩陣形狀變化(5000,10) --> (1,5000),加1是爲了與目標值類別(1,2,3...10)相對應。

判斷準確度:

# 判斷準確度
y_pre = np.mat(predict(all_theta, X))  # 預測值矩陣
y_true = np.mat(data['y']).ravel()  # 真實值矩陣
# 矩陣進行比較返回各元素比對布爾值矩陣,列表進行比較返回整個列表的比對布爾值
accuracy = np.mean(y_pre == y_true)
print('accuracy = {}%'.format(accuracy * 100))
複製代碼

結果:

2.前饋神經網絡

2.1 模型圖示

本練習基於訓練好的權重:

也就是說在不包括'+1'單元的前提下,第一層輸入層有400個單元,第二層隱層有25個單元,第三層輸出層有10個單元。

2.2 前饋預測(feed forward prediction)

# 第一層 --> 第二層
a1 = X
a1 = np.insert(a1, 0, values=np.ones(a1.shape[0]), axis=1)  # 加入+1單元
z2 = X @ theta1.T
a2 = sigmoid(z2)
a2 = np.insert(a2, 0, values=np.ones(a2.shape[0]), axis=1)  # 加入+1單元
複製代碼

此時a2.shape爲(5000,26)。

# 第二層 --> 第三層
z3 = a2 @ theta2.T
a3 = sigmoid(z3)
a3.shape
複製代碼

此時a3.shape爲(5000,10),已經算出每一個樣本屬於各個類別的機率。

2.3 計算準確度

# 計算準確度
y_predict = np.mat(np.argmax(a3,axis=1) + 1)  # 預測值矩陣
y_true = np.mat(y).ravel()  # 真實值矩陣
# 矩陣進行比較返回各元素比對布爾值矩陣,列表進行比較返回整個列表的比對布爾值
accuracy = np.mean(y_predict == y_true)
print('accuracy = {}%'.format(accuracy * 100))
複製代碼

結果:

accuracy = 97.52%

結論: 可將前饋預測過程看作多層多分類邏輯迴歸問題相疊加。

相關文章
相關標籤/搜索