题目:构建逻辑回归模型来识别数字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 + reg
def 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.x
return theta
def predict(X, theta):
h = sigmoid(X@theta.T)
h_argmax = np.argmax(h, axis=1)
return h_argmax + 1
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_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-05
7.22839979e-06 0.00000000e+00]
[-4.57041525e+00 0.00000000e+00 0.00000000e+00 ... -1.33611163e-03
9.99192279e-05 0.00000000e+00]
[-5.40239782e+00 0.00000000e+00 0.00000000e+00 ... -1.16450568e-04
7.86669421e-06 0.00000000e+00]]
0.9446
precision recall f1-score support
1 0.95 0.99 0.97 500
2 0.95 0.92 0.93 500
3 0.95 0.91 0.93 500
4 0.95 0.95 0.95 500
5 0.92 0.92 0.92 500
6 0.97 0.98 0.97 500
7 0.95 0.95 0.95 500
8 0.93 0.92 0.92 500
9 0.92 0.92 0.92 500
10 0.97 0.99 0.98 500
accuracy 0.94 5000
macro 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_report
def 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.9752
precision recall f1-score support
1 0.97 0.98 0.98 500
2 0.98 0.97 0.98 500
3 0.98 0.96 0.97 500
4 0.97 0.97 0.97 500
5 0.97 0.98 0.98 500
6 0.98 0.99 0.98 500
7 0.98 0.97 0.97 500
8 0.98 0.98 0.98 500
9 0.97 0.96 0.96 500
10 0.98 0.99 0.99 500
accuracy 0.98 5000
macro avg 0.98 0.98 0.98 5000
weighted avg 0.98 0.98 0.98 5000
总结:在构建多元分类的模型中,方法就是将其转化为二元分类,再做循环计算,这样每次只需要将本身看做为0或1即可,注意其每次循环时要取概率最高的那次才有意义。用神经网络时,其结果有点过于理想了,怀疑是出现了过拟合现象。