吴恩达机器学习神经网络作业(python实现)

1. 多分类逻辑回归

自动识别手写数字

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
from scipy.optimize import minimize
#  加载mat数据
def load_data(path):
    data = loadmat(path)
    X = data['X']
    y = data['y']
    return X,y
def plot_an_image(X):
    """
    随机打印一个数字
    """
    pick_one = np.random.randint(0, 5000)   # 随机选择行数
    image = X[pick_one, :]                # 提取一行中400个像素点
    fig, ax = plt.subplots(figsize=(1, 1))   # 一行一列的图像
    ax.matshow(image.reshape((20, 20)), cmap='gray_r')   # reshape函数将image重置为20*20的矩阵
    plt.xticks([])  # 去除x刻度
    plt.yticks([])  # 去除x刻度
    plt.show()
    print('this should be {}'.format(y[pick_one]))  # 输出图像代表的值

def plot_100_image(X):
    """
    随机画100个数字
    """
    sample_idx = np.random.choice(np.arange(X.shape[0]), 100)  # 随机选100个样本
    sample_images = X[sample_idx, :]  # (100,400)
    fig, ax_array = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True, figsize=(8, 8))
    for row in range(10):
        for column in range(10):
            ax_array[row, column].matshow(sample_images[10 * row + column].reshape((20, 20)),
                                          cmap='gray_r')
    plt.xticks([])
    plt.yticks([])
    plt.show()
# 定义sigmoid函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))
# 代价函数 不惩罚theta0 l是正则化常数
def regularized_cost(theta, X, y, l):
    thetaReg = theta[1:]
    first = (-y*np.log(sigmoid(X@theta))) + (y-1)*np.log(1-sigmoid(X@theta))
    reg = (thetaReg@thetaReg)*l / (2*len(X))
    return np.mean(first) + reg
#带惩罚的梯度下降
def regularized_gradient(theta, X, y, l):
    thetaReg = theta[1:]
    first = (1 / len(X)) * X.T @ (sigmoid(X @ theta) - y)
    # 这里人为插入一维0,使得对theta_0不惩罚,方便计算
    reg = np.concatenate([np.array([0]), (l / len(X)) * thetaReg])
    return first + reg

# 多分类
def one_vs_all(X, y, l, K):     # k是标签数
    """generalized logistic regression
    args:
        X: feature matrix, (m, n+1) # with incercept x0=1
        y: target vector, (m, )
        l: lambda constant for regularization
        K: numbel of labels
    return: trained parameters
    """
    all_theta = np.zeros((K, X.shape[1]))  # (10, 401)
    for i in range(1, K + 1):
        theta = np.zeros(X.shape[1])
        y_i = np.array([1 if label == i else 0 for label in y])
        ret = minimize(fun=regularized_cost, x0=theta, args=(X, y_i, l), method='TNC',    # 返回一组符合十种数字的参数
                       jac=regularized_gradient, options={
     'disp': True})
        all_theta[i - 1, :] = ret.x
    return all_theta

def predict_all(X, all_theta):
    h = sigmoid(X @ all_theta.T)  # 注意的这里的all_theta需要转置
    h_argmax = np.argmax(h, axis=1)  #找到每一行最大值的索引
    h_argmax = h_argmax + 1   #数组是0索引 需要加一个
    return h_argmax


# X, y = load_data('ex3data1.mat')
# print(X.shape, y.shape)
# plot_an_image(X)
# plot_100_image(X)
raw_X, raw_y = load_data('ex3data1.mat')
X = np.insert(raw_X, 0, 1, axis=1) # (5000, 401)
y = raw_y.flatten()  # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,)

all_theta = one_vs_all(X, y, 1, 10)
all_theta  # 每一行是一个分类器的一组参数
y_pred = predict_all(X, all_theta)
accuracy = np.mean(y_pred == y)
print ('accuracy = {0}%'.format(accuracy * 100))

2. 使用神经网络进行手写数字识别

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

def load_weight(path):
    data = loadmat(path)
    return data['Theta1'], data['Theta2']
#  1.读取已经计算好的参数
theta1, theta2 = load_weight('ex3weights.mat')
print(theta1.shape, theta2.shape)

X, y = load_data('ex3data1.mat')
y = y.flatten()
X = np.insert(X, 0, values=np.ones(X.shape[0]), axis=1)  #在第一列插入一列零

a1 = X
z2 = a1 @ theta1.T

z2 = np.insert(z2, 0, 1, axis=1)  #第二层加一列a0
a2 = sigmoid(z2)

z3 = a2 @ theta2.T    # 第三层
a3 = sigmoid(z3)

y_pred = np.argmax(a3, axis=1) + 1
accuracy = np.mean(y_pred == y)
print ('accuracy = {0}%'.format(accuracy * 100))  # accuracy = 97.52%

你可能感兴趣的:(机器学习)