吴恩达机器学习编程作业三 多分类以及前馈神经网络(python)

参考链接:https://blog.csdn.net/Cowry5/article/details/80367832

1.多分类分类器

将之前实施的logistic分类拓展到one-vs-all分类

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
from scipy.io import loadmat
1.1数据集

数据在ex3data1.mat。5000个训练样本,每个图片大小20×20转化为400维,矩阵X为5000×400。
在这里插入图片描述

#加载数据集,数据的格式为matlab格式,使用scipy.io的loadmat
def load_data(path):
	data = loadmat(path)
	X = data['X']
	y = data['y']
	return X,y
 X,y = load_data('ex3data1.mat')
 print(np.unique(y))#查看有积累标签

X.shape,y.shape

#有5000个训练样本,20×20的灰度图像,展开成400的向量
#5000×400的矩阵X
#将逻辑回归实现为完全向量化
#

[ 1 2 3 4 5 6 7 8 9 10]
((5000, 400), (5000, 1))

1.2可视化数据
def plot_an_image(X):
	'''
	随机打印一个数字
	'''
	pick_one = np.random.randint(0,5000)
	image=X[pick_one,:]
	fig,ax = plt.subplots(figsize=(1,1))
	ax.matshow(image.reshape((20,20)),cmap='gray_r')
	plt.xticks([])
	plt.yticks([])
	plt.show()
	print('this should be {}'.format(y[pick_one]))

在这里插入图片描述

def plot_100_image(X):
	'''
	随机画100个数字
	'''
	sample_idx = np.random.choice(np.arange(X.shape[0]),100)#随机选100个样本
	sample_images = X[sample_idx,:]#(100,400)
	fig,ax_array = plt.subplots(nrows=10,ncols=10,sharey=True,sharex=True,figsize=(8,8))
	for row in range(10):
		for column in range(10):
			ax_array[row,column].matshow(sample_images[10*row+column].reshape((20,20)),
				cmap='gray_r')
	plt.xticks([])
	plt.yticks([])
	plt.show()
plot_100_image(X)

在这里插入图片描述

1.3 向量化logistic回归

使用one-vs-all逻辑回归模型来构建一个多类分类器。既然有10类,需要训练10个分类logistic回归分类器。为了提高培训的效率使用向量化。实现不使用任何for循环的逻辑回归的向量化版本。可以使用上一个练习中的代码作为起点。
1.3.1 向量化代价函数
在这里插入图片描述
正则化:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

def sigmoid(z):
	return 1/(1+np.exp(-z))

def regularized_cost(theta,X,y,l):
	'''
	dont't oenalize theta_0
	args:
	X:feature matrix,(m,n+1);#插入了x0=1
	y: traget vector,(m,)
	l:lambda constant for regularization
	'''
	thetaReg = theta[1:]
	first = (-y*np.log(sigmoid(X@theta)))+(y-1)*np.log(1-sigmoid(X@theta))
	reg=(thetaReg@thetaReg)*l/(2*len(X))
	return np.mean(first)+reg

1.3.2 正则化向量化梯度
在这里插入图片描述

def regularized_gradient(theta,X,y,l):
	'''
	don't penalize theta_0
	args:
	l:lambda constant
	return:
	a vector of gradient
	'''
	thetaReg = theta[1:]
	first= (1/len(X))*X.T@(sigmoid(X @ theta) - y)
	#人为插入一组θ,使得对Θ0不惩罚,方便计算
	reg = np.concatenate([np.array([0]),(l/len(X))*thetaReg])
	return first +reg
1.4 一对多分类器

首先,我们为X添加了一列常数项 1 ,以计算截距项(常数项)。 其次,我们将y从类标签转换为每个分类器的二进制值(要么是类i,要么不是类i)。 最后,我们使用SciPy的较新优化API来最小化每个分类器的代价函数。 如果指定的话,API将采用目标函数,初始参数集,优化方法和jacobian(渐变)函数。 然后将优化程序找到的参数分配给参数数组。

实现向量化代码的一个更具挑战性的部分是正确地写入所有的矩阵,保证维度正确。
https://blog.csdn.net/Cowry5/article/details/80367832

from scipy.optimize import minimize

def one_vs_all(X,y,l,K):
    '''
    generalized logistic regression
    args:
        X: feature matrix,(m,n+1)#with incercept x0=1
        y: target vector,(m,)
        l: lambda constant for regurization
        k: numbel of labels
    return : trained parameters
    '''
    all_theta = np.zeros((K,X.shape[1]))
    for i in range(1,K+1):
        theta = np.zeros(X.shape[1])
        y_i = np.array([1 if label ==i else 0 for label in y])
        ret = minimize(fun=regularized_cost,x0=theta, args=(X, y_i,l),method = 'TNC',
                      jac=regularized_gradient,options = {'disp':True})
        all_theta[i-1,:] = ret.x #十个分类器
    return all_theta

1.4.1 一对多预测
一对所有预测函数将选择相应的logistic回归分类器输出的概率最大,且返回类标签(1,2,…,或K)作为输入示例的预测,在代码中预测类别需要+1

def predict_all(X,all_theta):
    # compute the class probability
    h = sigmoid(X @ all_theta.T)#(5000,10)
    #为最大可能的类别创建下标数组
    #返回最大值的切片
    h_argmax = np.argmax(h, axis=1)
    #因为我的数组是0索引,我们需要加一得到真实标签预测
    h_argmax = h_argmax+1
    
    return h_argmax  #5000个样本的预测值

raw_X,raw_y= load_data('ex3data1.mat')
X = np.insert(raw_X, 0,1,axis=1)
y = raw_y.flatten()

all_theta = one_vs_all(X,y,1,10)
all_theta

ex3.m将使用Θ的学习值。应该知道训练集的准确度94.9%(即对训练集中94.9%的例子进行了正确分类)。

y_pred = predict_all(X,all_theta)
accuracy = np.mean(y_pred == y)
print('accuracy = {0}%'.format(accuracy*100))

accuracy = 94.46%

2神经网络

使用训练好的权重实现一个前馈神经网络

def load_weight(path):
    data = loadmat(path)
    return data['Theta1'],data['Theta2']
theta1,theta2 =load_weight('ex3weights.mat')
theta1.shape, theta2.shape

((25, 401), (10, 26))

在数据加载函数中,原始数据做了转置,然而,转置的数据与给定的参数不兼容,因为这些参数是由原始数据训练的。 所以为了应用给定的参数,我需要使用原始数据(不转置)

#使用原始数据
X,y = load_data('ex3data1.mat')
y =y.flatten()
X = np.insert(X,0,values=np.ones(X.shape[0]),axis=1)
X.shape,y.shape

((5000, 401), (5000,))

a1 = X
z2 = a1@theta1.T
z2.shape

(5000, 25)

z2 = np.insert(z2,0,1,axis=1)
a2 = sigmoid(z2)
a2.shape

(5000, 26)

z3 = a2@ theta2.T
z3.shape

(5000, 10)

a3 = sigmoid(z3)
a3.shape

(5000, 10)

y_pred = np.argmax(a3,axis=1)+1
accuracy = np.mean(y_pred == y)
print('accuracy = {0}%'.format(accuracy*100))

accuracy = 97.52%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值