任务描述
数据集为手写数字,是一个多分类问题,分别用逻辑回归和神经网络做。
逻辑回归
逻辑回归及其正则化已经在 EX 2 做过,这里做一些修改即可。
首先导入数据,给出的数据集是 Matlab 的 .mat 格式,每个样本是 20 * 20 的灰度图,共 5000 个样本:
import numpy as np
from scipy.io import loadmat
import scipy.optimize as opt
def loadData(filename):
return loadmat(filename)
data = loadmat('ex3data1.mat')
print(data['X'].shape, data['y'].shape)
(5000, 400) (5000, 1)
Process finished with exit code 0
接着对数据预处理 ,因为是数字 0 ~ 9 的多分类问题,需要 10 个分类器,这里 theta 初始化为大小为 11 * n+1 的数组,11 是因为数字 0 的标签是 10,这样后续程序写起来比较简洁。
def initData(data):
# 样本数
m = data['X'].shape[0]
# 特征数
n = data['X'].shape[1]
# 增加一列 bias
data['X'] = np.append(data['X'], np.ones(m).reshape(m,1), axis=1)
X = data['X']
y = data['y']
theta = np.zeros((11, n + 1))
return X, y, theta
编写 Logistic Regression 需要的函数,详细内容可参考: 吴恩达机器学习CS229A_EX2_逻辑回归与正则化 。
这里根据要求对梯度求解函数做了改写,用矩阵运算替代循环,函数的计算结果和之前的是一样的。
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def costReg(theta, X, y, lamda):
n = len(theta)
m = len(y)
first = -y * np.log(sigmoid(X @ theta.reshape(n,1)))
second = -(1 - y) * np.log(1 - sigmoid(X @ theta.reshape(n,1)))
reg = (lamda / (2 * m)) * np.sum(np.power(theta.reshape(n,1), 2))
return (sum(first + second) / m) + reg
def gradientReg_noLoop(theta, X, y, lamda):
n = len(theta)
m = len(y)
error = sigmoid(X @ theta.reshape(n, 1)) - y
grad = (X.T @ error / m) + ((lamda / m) * theta.reshape(n, 1))
grad[0][0] = np.sum(error * X[:, 0].reshape(m, 1)) / m
grad = np.reshape(grad, (n,))
return grad
编写分类函数和测试函数:
# 分类函数
def one_vs_all(theta, X, y, lamda):
m = len(y)
n = len(theta[0])
# 从 1 到 10 总共训练 10 个分类器,依次保存到