题目:

  • 在本次练习中,你将使用逻辑回归神经网络来识别手写数字(从0到9)。
  • 今天,自动手写数字识别被广泛使用,从识别信封上的邮政编码到识别银行支票上的金额。这个练习将向你展示如何将你所学的方法用于此分类任务。
  • 在第一部分中,将扩展以前的逻辑回归,并将其应用于one-vs-all分类。
  • 关于数据:本次的数据是以.mat格式储存的,mat格式是matlab的数据存储格式,按照矩阵保存,与numpy数据格式兼容,适合于各种数学运算,因此这次主要使用numpy进行运算。
  • ex3data1中有5000个训练样例,其中每个训练样例是一个20像素×20像素灰度图像的数字,每个像素由一个浮点数表示,该浮点数表示该位置的灰度强度。每个20×20像素的网格被展开成一个400维的向量。这些每个训练样例都变成数据矩阵X中的一行。这就得到了一个5000×400矩阵X,其中每一行都是手写数字图像的训练样例。训练集的第二部分是一个包含训练集标签的5000维向量y,“0”的数字标记为“10”,而“1”到“9”的数字按自然顺序标记为“1”到“9”。

编程实现

1.Visualizing the data

加载数据集。这里的数据为MATLAB的格式,所以要使用SciPy.io的loadmat函数。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat # 这里的数据为MATLAB的格式,所以要使用SciPy.io的loadmat函数。
def load_data(path):
data = loadmat(path)
X = data['X']
y = data['y']
return X,y X, y = load_data('D:\BaiduNetdiskDownload\data_sets\ex3data1.mat') # unique() 统计list中的不同值时,返回的是array;用来看下有几类标签
print(np.unique(y)) X.shape, y.shape

其中有5000个训练样本,每个样本是20*20像素的数字的灰度图像。每个像素代表一个浮点数,表示该位置的灰度强度。20×20的像素网格被展开成一个400维的向量。在我们的数据矩阵X中,每一个样本都变成了一行,这给了我们一个5000×400矩阵X,每一行都是一个手写数字图像的训练样本。

def plot_an_image(X):
"""
随机打印一个数字
"""
pick_one = np.random.randint(0, 5000) # np.random.randint(a,b):用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n:a<=n<b,即[a,b)
image = X[pick_one, :]
fig, ax = plt.subplots(figsize=(1, 1))
ax.matshow(image.reshape((20, 20)), cmap='gray_r') # reshape()是数组对象中的方法,用于改变数组的形状。参数cmap='gray_r'是白底黑字的
plt.xticks([]) # 去除刻度,美观
plt.yticks([])
plt.show()
print('this should be {}'.format(y[pick_one])) plot_an_image(X)

#定义可视化函数
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)

2.Regularized Cost function

正则化逻辑回归的代价函数如下:

\[J(\theta)=\frac1m \sum_{i=1}^m \left( - y^{\left(i \right)} log \left( h_\theta \left( x^{\left( i\right)} \right) \right) - \left( 1-y^{\left( i\right)} \right) log \left( 1- h_\theta \left( x^{\left( i\right)} \right) \right) \right) + \frac {\lambda}{2m} \sum_{j=1}^n \theta_j^2
\]

注意: 不惩罚第一项\(\theta_0\)

def sigmoid(z):
return 1 / (1 + np.exp(-z)) # 定义带正则项的代价函数
def regularized_cost(theta, X, y, l):
"""
don't penalize theta_0
args:
X: feature matrix, (m, n+1) # 插入了x0=1
y: target vector, (m, )
l: lambda constant for regularization
"""
thetaReg = theta[1:] # 将theta的第二列到最后一列的内容赋给theta
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

3.Regularized gradient

因为我们未对\({\theta }_{0}\)进行正则化,所以梯度下降算法将分两种情形:

\[\frac{\partial }{\partial \theta_0} J(\theta)=\frac1m \sum_{i=1}^m \left( h_\theta \left( x^{ \left(i\right) } \right) -y^{ \left(i\right) } \right) x_{0}^{\left(i\right)}
\]

\[\frac{\partial }{\partial \theta_j} J(\theta)=\frac1m \sum_{i=1}^m \left( h_\theta \left( x^{ \left(i\right) } \right) -y^{ \left(i\right) } \right) x_{j}^{\left(i\right)} + \frac \lambda m \theta_j,其中j=1,2,\cdots,n
\]

# 定义正则化梯度值(导数值)
def regularized_gradient(theta, X, y, l):
"""
don't penalize theta_0
args:
l: lambda constant for regularization
return:
a vector of gradient
"""
thetaReg = theta[1:]
first = (1 / len(X)) * X.T @ (sigmoid(X @ theta) - y) # 这里插入一维0,使得对theta_0不惩罚,方便计算
reg = np.concatenate([np.array([0]), (l / len(X)) * thetaReg]) # 将具有相同结构的array序列结合成一个array
return first + reg

4.One-vs-all Classification

这部分我们将实现一对多分类通过训练多个正则化logistic回归分类器,每个对应数据集中K类中的一个。利用for循环对每种数字习得一个带正则的逻辑回归分类器,然后将10个分类器的参数组成一个参数矩阵all_theta返回。

from scipy.optimize import minimize

#计算K个类别分别训练出来的参数theta
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 regularization
K: numbel of labels
return: trained parameters
"""
all_theta = np.zeros((K, X.shape[1])) # (10, 401) 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]) # 如果y对应的值和i相等就返回1,否则返回0 # minimize是局部最优的解法
# fun: 求最小值的目标函数
# x0:变量的初始猜测值,如果有多个变量,需要给每个变量一个初始猜测值
# args:是传递给优化函数的参数
# method:求极值的方法
# jac:计算梯度向量的方法
# options:A dictionary of solver options.
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

对于这个任务,我们有10个可能的类,并且由于logistic回归只能一次在2个类之间进行分类,每个分类器在“类别 i”和“不是 i”之间决定。 我们将把分类器训练包含在一个函数中,该函数计算10个分类器中的每个分类器的最终权重,并将权重返回shape为(k, (n+1))数组,其中 n 是参数数量。

def predict_all(X, all_theta):

    # compute the class probability for each class on each training instance
# 这里的h共5000行,10列,每行代表一个样本,每列是预测对应数字的概率。
h = sigmoid(X @ all_theta.T) # 注意的这里的all_theta需要转置 # create array of the index with the maximum probability
# Returns the indices of the maximum values along an axis.
h_argmax = np.argmax(h, axis=1) # 返回h矩阵中每一行的最大索引 # because our array was zero-indexed we need to add one for the true label prediction
h_argmax = h_argmax + 1 #概率最大对应的index加1就是我们分类器最终预测出来的类别 return h_argmax

这里的h共5000行,10列,每行代表一个样本,每列是预测对应数字的概率,是一个5000乘10的预测概率矩阵。我们取概率最大对应的index加1就是我们分类器最终预测出来的类别。返回的h_argmax是一个array,包含5000个样本对应的预测值。

5.Learning θ parameters

raw_X, raw_y = load_data('D:\BaiduNetdiskDownload\data_sets\ex3data1.mat')

X = np.insert(raw_X, 0, 1, axis=1) # 为X添加了一列常数项 1,(5000, 401)

y = raw_y.flatten()  # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,)

all_theta = one_vs_all(X, y, 1, 10)
all_theta # 每一行是一个分类器的一组参数

6.Evaluating logistic regression

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

总结

有K个分类器,每个分类要针对其中一种情况进行训练。也就是每个分类分别当做1,不是这个分类的当做0,进行上次作业中的逻辑回归的二分类任务。

参考资料

minimize官方文档

吴恩达机器学习作业Python实现(三):多类分类和前馈神经网络

吴恩达|机器学习作业3.0.逻辑回归解决多元分类

编程作业3.1:Multi-class classification(One-vs-all)的更多相关文章

  1. Stanford coursera Andrew Ng 机器学习课程编程作业(Exercise 2)及总结

    Exercise 1:Linear Regression---实现一个线性回归 关于如何实现一个线性回归,请参考:http://www.cnblogs.com/hapjin/p/6079012.htm ...

  2. stanford coursera 机器学习编程作业 exercise 3(逻辑回归实现多分类问题)

    本作业使用逻辑回归(logistic regression)和神经网络(neural networks)识别手写的阿拉伯数字(0-9) 关于逻辑回归的一个编程练习,可参考:http://www.cnb ...

  3. 吴恩达深度学习第2课第2周编程作业 的坑(Optimization Methods)

    我python2.7, 做吴恩达深度学习第2课第2周编程作业 Optimization Methods 时有2个坑: 第一坑 需将辅助文件 opt_utils.py 的 nitialize_param ...

  4. Coursera公开课-Machine_learing:编程作业3

    第四周 编程作业: Multi-class Classification and Neural Networks 这周作业与上一周有许多相同的部分,比如longistic regression中的lr ...

  5. 11061160_11061151_Pair Project: Elevator Scheduler软件工程结对编程作业总结

    软件工程结对编程作业总结 11061160  顾泽鹏 11061151  庞梦劼 一.关于结对编程 这次的软工任务既不是单打独斗的个人任务,也不是集思广益的团队项目,而是人数为两人的结对编程.两个人合 ...

  6. ufldl学习笔记和编程作业:Feature Extraction Using Convolution,Pooling(卷积和汇集特征提取)

    ufldl学习笔记与编程作业:Feature Extraction Using Convolution,Pooling(卷积和池化抽取特征) ufldl出了新教程,感觉比之前的好,从基础讲起.系统清晰 ...

  7. ufldl学习笔记和编程作业:Softmax Regression(softmax回报)

    ufldl学习笔记与编程作业:Softmax Regression(softmax回归) ufldl出了新教程.感觉比之前的好,从基础讲起.系统清晰,又有编程实践. 在deep learning高质量 ...

  8. 关于Coursera上的斯坦福机器学习课程的编程作业提交问题

    学习Coursera上的斯坦福机器学习课程的时候,需要向其服务器提交编程作业,我遇到如下问题: 'Submission failed: unexpected error: urlread: Peer ...

  9. 吴恩达深度学习第4课第3周编程作业 + PIL + Python3 + Anaconda环境 + Ubuntu + 导入PIL报错的解决

    问题描述: 做吴恩达深度学习第4课第3周编程作业时导入PIL包报错. 我的环境: 已经安装了Tensorflow GPU 版本 Python3 Anaconda 解决办法: 安装pillow模块,而不 ...

随机推荐

  1. (转)解决windows解决windows 7 部分程序图标显示不正常的问题

    刚解决计算机的管理选项打开出现问题,又发现系统里部分程序的快捷图标显示不出了, 曾在xp里也出现过同样的问题,常理推断,如果系统没有被病毒破坏那可能就是系统图标缓存出现问题 因此,双管齐下,一边检查系 ...

  2. css画布

    绘制基本图形 绘制直线 <style> .canvas{ } </style> <canvas id="myCanvas1" style=" ...

  3. 054-for循环

    <?php for($i=1;$i<=5;$i++){ echo "$i<br />"; //循环体 } ?>

  4. Maven的安装和创建项目的过程

    一.下载Maven包和配置环境变量 1.将下载好的maven包放到一个目录中:目录中不能有汉字和空格 2.配置环境变量 3.配置path路径 二.配置阿里云私服 1.找到setting目录,配置下载j ...

  5. junit基础学习之-junit3和4的区别(4)

    junit3和junit4的使用区别如下 1.在JUnit3中需要继承TestCase类,但在JUnit4中已经不需要继承TestCase 2.在JUnit3中需要覆盖TestCase中的setUp和 ...

  6. python转换ascii码

    字符转数字 ord("A") 数字转字符 chr(65)

  7. 每天一点点之vue框架开发 - vue-router路由进阶(路由别名、跳转、默认路由、二级路由、路由守卫)

    路由别名   在main.js中的路由中添加name来创建别名 const routes = [ {path:'/footer',name:footerLink,component:Footer} ] ...

  8. 个人网站一步一步搭建——(20)成功在本地IIS运行

    昨天网站都做完了,今天发布.然后在IIS运行成功了. 遇到了很多问题  发布了不低于10次 头都晕了. 问题1:之前写了很多调试代码 console.log(); 慢慢删除完,. 问题2:vue 不能 ...

  9. 对DataFrame的再理解

    1.构造需要从字典构造 cds={'code':["002372.XSHE","002415.XSHE","002304.XSHE",&qu ...

  10. Maven工程配置依赖

    1.下载 安装 官网下载maven :http://maven.apache.org/download.cgi ,下载时候注意版本,IDEA旧版本如我用的2017在安装Maven时可能会报错,此时别下 ...