吴恩达机器学习第三次作业
这次作业第一部分手写数字的识别,是一个多分类问题。首先我想到可以在上次作业的基础上进行改造,即把训练十个二分类器,然后最终确定数字的类别。
首先是数据的处理展示。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
from scipy.io import loadmat
from sklearn.metrics import classification_report#这个包是评价报告
path = 'C:/Users/ASUS/Desktop/ex3data1.mat'
data = loadmat(path)
data['X'].shape,data['y'].shape#X的形状(5000, 400),y的形状(5000, 1)
data['y'][[10,2001,1000],:]#读取第11、2002、1001张图片对应的数字看看
#展示100张图片
sample_index = np.random.randint(0,5001,100)
sample_images = data['X'][sample_index,:]
fig, ax_array = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True, figsize=(12, 12))#sharey=True, sharex=True共享x轴和y轴的属性
for r in range(10):
for c in range(10):
#ax_array[r, c].matshow((sample_images[10 * r + c].reshape((20, 20))).T,cmap=matplotlib.cm.binary)
ax_array[r, c].imshow((sample_images[10 * r + c].reshape((20, 20))).T,cmap=matplotlib.cm.binary)
plt.xticks([])
plt.yticks([]) #去掉y轴上的刻度
raw_x_temp = data['X']
raw_y = data['y']
raw_x = np.insert(raw_x_temp,0,1,axis=1)
随机取出的100个数如上图。
之后进行十个二分类器的训练。
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def cost(theta, x, y,lamda):
a = np.mat(theta)
b = a.T
loss_1 = ((np.log(sigmoid(a*x.T))*y)+(np.log(1-sigmoid(a*x.T))*(1-y)))/(-x.shape[0])
loss = loss_1+ lamda*(a*b-theta[0]**2)/(2*x.shape[0])
return loss
def gradient(theta, x, y,lamda):
a = np.mat(theta)
b = a.T
reg = lamda*a[0,1:]
reg = np.insert(reg,0,values=0,axis=1)
gra = (((sigmoid(x*b) - y).T)*x + reg)/x.shape[0]
return gra
#数字n为正类,其余为负类
def divide_data(raw_y,raw_x,n):
raw_y1=raw_y.flatten()
index_n=np.where(raw_y1 == n)
x = raw_x
y = np.zeros_like(raw_y)
y[[index_n],:] = 1
return x,y
def gettheta(raw_y,raw_x,n,lamda,theta):
x,y = divide_data(raw_y,raw_x,n)
result = opt.fmin_tnc(func=cost, x0=theta, fprime=gradient, args=(x, y,lamda))
return result[0]
lamda=0.01
theta = np.zeros(raw_x.shape[1])
import scipy.optimize as opt
theta_all = []
for i in range(10):
theta_all.append(gettheta(raw_y,raw_x,i+1,lamda,theta))
last_theta = np.array(theta_all)```
最后检验正确率。
#第一种算正确率的方法
h = sigmoid(np.dot(raw_x,last_theta.T))
h_argmax = np.argmax(h, axis=1)+1 #h形状是(5000,10),取出最大值是0到9需要加1
acc = np.mean(h_argmax==raw_y.flatten()) #计算正确率 结果为0.97
#第二种可视化正确率的方法
print(classification_report(raw_y, h_argmax))
第二种方法得到的报告如下图所示。
第二部分是前馈神经网络,其中网络的权重参数已经给出,主要是体会一下前向传播的过程。
path = 'C:/Users/ASUS/Desktop/ex3weights.mat'
weight = loadmat(path)
theta1, theta2 = weight['Theta1'], weight['Theta2']
def sigmoid(z):
return 1 / (1 + np.exp(-z))
a_1 = raw_x
z_2 = np.dot(a_1,theta1.T)
a_2 = sigmoid(z_2)
a_2_new = np.insert(a_2,0,1,axis=1)
z_3 = np.dot(a_2_new,theta2.T)
a_3 = sigmoid(z_3)
y_pred = np.argmax(a_3, axis=1) + 1
acc = np.mean(y_pred==raw_y.flatten())