实验1:预测手写数字的识别
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.io as sio
from scipy.optimize import minimize
# 预测true flase
def predict(X, theta_final):
h = sigmoid(X @ theta_final.T) # 5000x401 10x401 > 5000x10
h_argmax = np.argmax(h, axis=1) # 沿着每一行所有列比较最大
return h_argmax + 1 # 索引返回最大的 因为下标是0比较的数字从1开始 加1 最后10代表0
#返回最终的K个训练器的theta
def one_vs_all(X, y, lamda, K):
n = X.shape[1]
theta_all = np.zeros((K, n))
for i in range(1, K + 1):
theta_i = np.zeros(n, ) #每个分类器的theta
res = minimize(fun=costFunction,
x0=theta_i,
args=(X, y == i, lamda),
method='TNC',
jac=gradient_reg) #
theta_all[i - 1, :] = res.x #相当于训练完的所有分类器的最佳参数返回
return theta_all
##显示样本中的图片
def plot_an_image(X):
picek_one = np.random.randint(5000)
image = X[picek_one, :]
fig, ax = plt.subplots(figsize=(1, 1))
ax.imshow(image.reshape(20, 20).T, cmap='gray_r') # 翻转过来T
plt.xticks([]) #
plt.yticks([]) # 去掉轴的刻度
plt.show() ##加这个才能显示
# 随机100张图片
def plot_100_image(X):
sample_index = np.random.choice(len(X), 100)
images = X[sample_index, :]
fig, ax = plt.subplots(figsize=(8, 8), ncols=10, nrows=10, sharex=True, sharey=True) # 10行10列同时共享刻度
for i in range(10):
for c in range(10):
ax[i, c].imshow(images[i * 10 + c, :].reshape(20, 20).T, cmap='gray_r') # 翻转过来T
# ax.imshow(image.reshape(20, 20).T, cmap='gray_r') #翻转过来T
plt.xticks([]) #
plt.yticks([]) # 去掉轴的刻度
plt.show() ##加这个才能显示
# 实现sigmoid函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 实现逻辑回归的代价函数,两个部分,-y(log(hx)和-(1-y)log(1-hx)
def costFunction(theta, X, y, lamda): ## scipy传参要求必须换位置
A = sigmoid(X @ theta)
first = y * np.log(A)
second = (1 - y) * np.log(1 - A)
# reg = np.sum(np.power(theta[1:], 2)) * (lamda / (2 * len(X)))
reg = theta[1:] @ theta[1:] * (lamda / (2 * len(X))) # thete在这个里面是1维的@就行了
return -np.sum(first + second) / len(X) + reg
# 梯度下降函数
def gradient_reg(theta, X, y, lamda):
reg = theta[1:] * (lamda / len(X))
reg = np.insert(reg, 0, values=0, axis=0) ###加一行否则矩阵不匹配
first = (X.T @ (sigmoid(X @ theta) - y)) / len(X)
return first + reg
data = sio.loadmat('ex3data1.mat')
# print(data)
# print(data.keys())
######np.dot np.matmul a @ b 叫矩阵乘法 np.mulitply * 是对于元素乘法
raw_x = data['X']
raw_y = data['y']
print(raw_x.shape) # 5000千个样本 400维 每个样本其实本来是20x20压缩到了400
plot_an_image(raw_x)
plot_100_image(raw_x)
X = np.insert(raw_x, 0, values=1, axis=1) ##每一行多加第一位0 401维度了
y = raw_y.flatten()
lamda = 1
K = 10
theta_final = one_vs_all(X, y, lamda, K) # 最终的10个分类器的theta
print(theta_final)
y_pred = predict(X, theta_final) # 预测
acc = np.mean(y_pred == y)
print(acc)
效果图:
准确率:
实验2 简单的前向传播过程
import numpy as np
import scipy.io as sio
# 实现sigmoid函数 激活函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
data = sio.loadmat('ex3data1.mat')
raw_x = data['X']
raw_y = data['y']
X = np.insert(raw_x, 0, values=1, axis=1)
y = raw_y.flatten()
theta = sio.loadmat('ex3weights.mat') # 直接拿到最佳参数
theta1 = theta["Theta1"] # 第一层
theta2 = theta["Theta2"] # 第二层参数
print(theta1.shape, theta2.shape)
a1 = X
z2 = X @ theta1.T ##简单的前向传递
a2 = sigmoid(z2)
a2 = np.insert(a2, 0, values=1, axis=1) #每一层都有个 b 此默认1
z3 = a2 @ theta2.T
a3 = sigmoid(z3)
y_pred = np.argmax(a3, axis=1)
y_pred = y_pred + 1
acc = np.mean(y_pred == y)
print(acc)
效果图: