题目:构建逻辑回归模型来识别数字0-9
代码如下:
import numpy as np
from scipy.io import loadmat
import scipy.optimize as opt
from sklearn.metrics import classification_report# 定义函数sigmoid,方便后续假设函数以sigmoid(z)表示
def sigmoid(z):return 1 / (1 + np.exp(-z))# 定义代价函数
def computeCost (theta, X, y, l=1 ):predictions = sigmoid(X @ theta)first = y * np.log(predictions)second = (1 - y) * np.log(1 - predictions)reg = theta[1:]@theta[1:]*(l/(2*len(X))) #正则化项return -np.sum(first + second)/len(X) +reg # 返回标量def gradient(theta, X, y, l=1):reg = theta[1:] * (l/len(X))reg = np.insert(reg, 0, values=0, axis=0)first = (X.T@(sigmoid(X@theta)-y))/len(X)return first + regdef one_vs_all(X, y, l=1, K = 10):n = X.shape[1]theta = np.zeros((K, n)) #创建与X的列数相同长度的0数组for i in range(1, K+1):theta_i = np.zeros(n, )res = opt.minimize(fun=computeCost,x0=theta_i,args=(X, y==i, l),method='TNC',jac=gradient)theta[i-1, :] = res.xreturn thetadef predict(X, theta):h = sigmoid(X@theta.T)h_argmax = np.argmax(h, axis=1)return h_argmax + 1data = loadmat('ex3data1.mat')
raw_x = data['X']
raw_y = data['y']
X = np.insert(raw_x, 0, values=np.ones(raw_x.shape[0]), axis=1)
y = raw_y.flatten()
print(y.shape)
theta_all = one_vs_all(X, y, l=1, K=10)
print(theta_all)
y_pred = predict(X, theta_all)
acc = np.mean(y_pred == y)
print(acc)
print(classification_report(y, y_pred))
输出:
(5000,)
[[-2.38017165e+00 0.00000000e+00 0.00000000e+00 ... 1.30445260e-03-7.38340466e-10 0.00000000e+00][-3.18105182e+00 0.00000000e+00 0.00000000e+00 ... 4.45068628e-03-5.07434671e-04 0.00000000e+00][-4.79899590e+00 0.00000000e+00 0.00000000e+00 ... -2.86819678e-05-2.48325958e-07 0.00000000e+00]...[-7.98439304e+00 0.00000000e+00 0.00000000e+00 ... -8.94750803e-057.22839979e-06 0.00000000e+00][-4.57041525e+00 0.00000000e+00 0.00000000e+00 ... -1.33611163e-039.99192279e-05 0.00000000e+00][-5.40239782e+00 0.00000000e+00 0.00000000e+00 ... -1.16450568e-047.86669421e-06 0.00000000e+00]]
0.9446precision recall f1-score support1 0.95 0.99 0.97 5002 0.95 0.92 0.93 5003 0.95 0.91 0.93 5004 0.95 0.95 0.95 5005 0.92 0.92 0.92 5006 0.97 0.98 0.97 5007 0.95 0.95 0.95 5008 0.93 0.92 0.92 5009 0.92 0.92 0.92 50010 0.97 0.99 0.98 500accuracy 0.94 5000macro avg 0.94 0.94 0.94 5000
weighted avg 0.94 0.94 0.94 5000
用神经网络前向传播计算准确率代码:
from scipy.io import loadmat
import numpy as np
from sklearn.metrics import classification_reportdef sigmoid(z):return 1 / (1 + np.exp(-z))data = loadmat('ex3data1.mat')
raw_x = data['X']
raw_y = data['y']
X = np.insert(raw_x, 0, values=np.ones(raw_x.shape[0]), axis=1)
y = raw_y.flatten()
print(y.shape)
theta = loadmat('ex3weights.mat')
theta1 = theta['Theta1']
theta2 = theta['Theta2']a1 = X
z2 = X@theta1.T
a2 = sigmoid(z2)
a2 = np.insert(a2, 0, values=1, axis=1)
z3 = a2@theta2.T
a3 = sigmoid(z3)
y_pred = np.argmax(a3, axis=1) + 1
acc = np.mean(y_pred == y)
print(acc)
print(classification_report(y, y_pred))
输出:
(5000,)
0.9752precision recall f1-score support1 0.97 0.98 0.98 5002 0.98 0.97 0.98 5003 0.98 0.96 0.97 5004 0.97 0.97 0.97 5005 0.97 0.98 0.98 5006 0.98 0.99 0.98 5007 0.98 0.97 0.97 5008 0.98 0.98 0.98 5009 0.97 0.96 0.96 50010 0.98 0.99 0.99 500accuracy 0.98 5000macro avg 0.98 0.98 0.98 5000
weighted avg 0.98 0.98 0.98 5000
总结:在构建多元分类的模型中,方法就是将其转化为二元分类,再做循环计算,这样每次只需要将本身看做为0或1即可,注意其每次循环时要取概率最高的那次才有意义。用神经网络时,其结果有点过于理想了,怀疑是出现了过拟合现象。
视频订正参考:【作业讲解】编程作业3:神经网络(上)_哔哩哔哩_bilibili