小白入門 吳恩達機器學習作業(三) python實現 詳細解析

本作業是實現十個邏輯迴歸的分類器。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat

mat數據格式是Matlab的數據存儲的標準格式。在python中可以使用scipy.io中的函數loadmat()讀取mat文件,函數savemat保存文件。

#加載數據
data = loadmat('ex3data1.mat')
data, data['X'].shape, data['y'].shape
({'__header__': b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Oct 16 13:09:09 2011',
  '__version__': '1.0',
  '__globals__': [],
  'X': array([[0., 0., 0., ..., 0., 0., 0.],
         [0., 0., 0., ..., 0., 0., 0.],
         [0., 0., 0., ..., 0., 0., 0.],
         ...,
         [0., 0., 0., ..., 0., 0., 0.],
         [0., 0., 0., ..., 0., 0., 0.],
         [0., 0., 0., ..., 0., 0., 0.]]),
  'y': array([[10],
         [10],
         [10],
         ...,
         [ 9],
         [ 9],
         [ 9]], dtype=uint8)},
 (5000, 400),
 (5000, 1))

X表示五千個樣本,一個400維。400維?:20*20的圖像,排成一個行向量;
y表示從1到10的數字。

#sigmoid函數
def sigmoid(z):
    return 1/(1+np.exp(-z))

y,np.log(sigmoid(X * theta.T))都是兩個5000*1的矩陣

def cost(theta, X, y, learningRate):
	#轉換成矩陣
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    #轉換成numpy類型的矩陣
    
    #np.multiply不是矩陣乘法,而是把這兩個矩陣對應的位置直接相乘
    #最後得到的還是一個5000*1的矩陣
    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))
    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))
    
    #損失函數的正則化部分,第一位theta是偏置,我們加上的,所以這裏不取
    reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))    
    return np.sum(first - second) / len(X) + reg

向量化的梯度函數

def gradient(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    
    parameters = int(theta.ravel().shape[1])
    error = sigmoid(X * theta.T) - y
    
    grad = ((X.T * error) / len(X)).T + ((learningRate / len(X)) * theta)
    
    #theta的第一維不需要正則化,所以重置    
    grad[0, 0] = np.sum(np.multiply(error, X[:,0])) / len(X)
    
    #把10*400壓縮成40000
    return np.array(grad).ravel()

all_theta在循環中每次處理一行,就是每次處理一個分類器,得到一個最優的theta

from scipy.optimize import minimize

def one_vs_all(X, y, num_labels, learning_rate):
    #10個lable, 1到10
    rows = X.shape[0] #行數,樣本個數
    params = X.shape[1] #列數,一個圖片的維度
    
    # k X (n + 1) array for the parameters of each of the k classifiers
    all_theta = np.zeros((num_labels, params + 1))
    #行。列:10, 401, 1是偏置
    
    # insert a column of ones at the beginning for the intercept term
    X = np.insert(X, 0, values=np.ones(rows), axis=1)
    #插一列,五千個樣本 。np.ones值爲1.在0的維度,按列的方向
    
    # labels are 1-indexed instead of 0-indexed
    for i in range(1, num_labels + 1):
        theta = np.zeros(params + 1) #401維的向量
        y_i = np.array([1 if label == i else 0 for label in y]) 
        #在構建第一個分類器,當標籤爲1的就是1,別的都置爲0
        y_i = np.reshape(y_i, (rows, 1)) #把他reshape成一個列向量
        
        # minimize the objective function
        fmin = minimize(fun=cost, x0=theta, args=(X, y_i, learning_rate), method='TNC', jac=gradient)
        all_theta[i-1,:] = fmin.x
        #i=1時就是第0行, 遍歷了每一行每一個邏輯迴歸的分類器
    
    return all_theta     

得到我們想要的參數

all_theta = one_vs_all(data['X'], data['y'], 10, 1)
type(all_theta),all_theta.shape
(numpy.ndarray, (10, 401))

用訓練好的模型進行預測。

def predict_all(X, all_theta):
    rows = X.shape[0]
    params = X.shape[1]
    num_labels = all_theta.shape[0]
    X = np.insert(X, 0, values=np.ones(rows), axis=1)
    X = np.matrix(X)
    all_theta = np.matrix(all_theta)
    
    # 計算每個樣本的分類
    h = sigmoid(X * all_theta.T)
    #變成了一個5000*10的矩陣,一行一個矩陣
    #這一行裏,第一列是分成1的概率,最大的就是應該取哪個lable
    
    h_argmax = np.argmax(h, axis=1)
    #沿着行找最大值, 5000*1,就是當前行最大概率的是哪個lable
    
    h_argmax = h_argmax + 1
    #第0列是lable1,so +1
    
    return h_argmax

輸入數據和模型,預測,計算精確度

y_pred = predict_all(data['X'], all_theta)
correct = [1 if a == b else 0 for (a, b) in zip(y_pred, data['y'])]
accuracy = (sum(correct) / float(len(correct)))
accuracy
0.9446
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章