Python机器学习的练习系列共有八个部分:

在Python机器学习的练习第3部分中,我们实现了简单的和正则化的逻辑回归。但我们的解决方法有一个限制—它只适用于二进制分类。在本文中,我们将在之前的练习中扩展我们的解决方案,以处理多级分类问题。

在语法上快速标注,为了显示语句的输出,我在代码块中附加了一个“>”,以表明它是运行先前语句的结果。如果结果很长(超过1-2行),那么我就把它粘贴在代码块的另一个单独的块中。希望可以清楚的说明哪些语句是输入,哪些是输出。

此练习中的任务是使用逻辑回归来识别手写数字(0-9)。首先加载数据集。与前面的示例不同,我们的数据文件是MATLAB的本体格式,不能被pandas自动识别,所以把它加载在Python中需要使用SciPy utility。

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from scipy.io import loadmat

%matplotlib inline

data = loadmat('data/ex3data1.mat')

data

{'X': array([[ 0., 0., 0., ..., 0., 0., 0.],

[ 0., 0., 0., ..., 0., 0., 0.],

[ 0., 0., 0., ..., 0., 0., 0.],

...,

[ 0., 0., 0., ..., 0., 0., 0.],

[ 0., 0., 0., ..., 0., 0., 0.],

[ 0., 0., 0., ..., 0., 0., 0.]]),

'__globals__': [],

'__header__': 'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Oct 16 13:09:09 2011',

'__version__': '1.0',

'y': array([[10],

[10],

[10],

...,

[ 9],

[ 9],

[ 9]], dtype=uint8)}

快速检查加载到储存器中的矩阵的形状

data['X'].shape, data['y'].shape

> ((5000L, 400L), (5000L, 1L))

我们已经加载了我们的数据。图像在martix X 被表现为400维的向量。这400个“特征”是原始20×20图像中每个像素的灰度强度。类标签在向量y中表示图像中数字的数字类。下面的图片给出了一些数字的例子。每个带有白色手写数字的灰色框代表我们数据集中400维的行。

我们的第一个任务是修改逻辑回归的实现以完全向量化(即没有“for”循环),这是因为矢量化代码除了简洁扼要,还能够利用线性代数优化,并且比迭代代码快得多。我们在练习二中的成本函数实现已经向量化。所以我们在这里重复使用相同的实现。请注意,我们正在跳到最终的正则化版本。

def sigmoid(z):

return 1 / (1 + np.exp(-z))

def cost(theta, X, y, learningRate):

theta = np.matrix(theta)

X = np.matrix(X)

y = np.matrix(y)

first = np.multiply(-y, np.log(sigmoid(X * theta.T)))

second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))

reg = (learningRate / 2 * len(X)) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))

return np.sum(first - second) / (len(X)) + reg

这个成本函数与我们在先前练习中创建的函数是相同的,如果你不确定我们如何做到这一点,在运行之前查看以前的文章。

接下来,我们需要计算梯度的函数。我们已经在前面的练习中定义了它,我们在更新步骤中需要去掉“for”循环。这是可供参考的原始代码:

def gradient_with_loop(theta, X, y, learningRate):

theta = np.matrix(theta)

X = np.matrix(X)

y = np.matrix(y)

parameters = int(theta.ravel().shape[1])

grad = np.zeros(parameters)

error = sigmoid(X * theta.T) - y

for i in range(parameters):

term = np.multiply(error, X[:,i])

if (i == 0):

grad[i] = np.sum(term) / len(X)

else:

grad[i] = (np.sum(term) / len(X)) + ((learningRate / len(X)) * theta[:,i])

return grad

梯度函数详细的阐述了如何改变一个参数,以获得一个比之前好的答案。如果你不熟悉线性代数,这一系列运作背后的数学是很难理解的。

现在我们需要创建一个不使用任何循环的梯度函数的版本。在我们的新版本中,我们将去掉“for”循环,并使用线性代数(除了截距参数,它需要单独计算)计算每个参数的梯度。

还要注意,我们将数据结构转换为NumPy矩阵。这样做是为了使代码看起来更像Octave,而不是数组,这是因为矩阵自动遵循矩阵运算规则与element-wise运算。我们在下面的例子中使用矩阵。

def gradient(theta, X, y, learningRate):

theta = np.matrix(theta)

X = np.matrix(X)

y = np.matrix(y)

parameters = int(theta.ravel().shape[1])

error = sigmoid(X * theta.T) - y

grad = ((X.T * error) / len(X)).T + ((learningRate / len(X)) * theta)

# intercept gradient is not regularized

grad[0, 0] = np.sum(np.multiply(error, X[:,0])) / len(X)

return np.array(grad).ravel()

现在我们已经定义了成本和梯度函数,接下来创建一个分类器。对于本章练习的任务,我们有10个可能的分类,由于逻辑回归一次只能区分两个类别,我们需要一个方法去处理多类别场景。在这个练习中我们的任务是实现一对多的分类,其中k个不同类的标签导致了k个分类器,每个分类器在“class i”和“not class i”之间做决定。我们将在一个函数中完成分类器的训练,计算10个分类器的最终权重,并将权重返回作为k X(n + 1)数组,其中n是参数数。

from scipy.optimize import minimize

def one_vs_all(X, y, num_labels, learning_rate):

rows = X.shape[0]

params = X.shape[1]

# k X (n + 1) array for the parameters of each of the k classifiers

all_theta = np.zeros((num_labels, params + 1))

# insert a column of ones at the beginning for the intercept term

X = np.insert(X, 0, values=np.ones(rows), axis=1)

# labels are 1-indexed instead of 0-indexed

for i in range(1, num_labels + 1):

theta = np.zeros(params + 1)

y_i = np.array([1 if label == i else 0 for label in y])

y_i = np.reshape(y_i, (rows, 1))

# minimize the objective function

fmin = minimize(fun=cost, x0=theta, args=(X, y_i, learning_rate), method='TNC', jac=gradient)

all_theta[i-1,:] = fmin.x

return all_theta

这里需要注意的几点:首先,我们为theta添加了一个额外的参数(带有一列训练数据)以计算截距项。其次,我们将y从类标签转换为每个分类器的二进制值(要么是I类,要么不是I类)。最后,我们使用SciPy的较新优化API来最小化每个分类器的成本函数。API利用目标函数、初始参数集、优化方法和jacobian(梯度)函数,将优化程序找到的参数分配给参数数组。

实现向量化代码的一个更具挑战性的部分是正确地写入所有的矩阵交互,所以通过查看正在使用的数组/矩阵的形状来做一些健全性检查是有用的,我们来看看上面的函数中使用的一些数据结构。

rows = data['X'].shape[0]

params = data['X'].shape[1]

all_theta = np.zeros((10, params + 1))

X = np.insert(data['X'], 0, values=np.ones(rows), axis=1)

theta = np.zeros(params + 1)

y_0 = np.array([1 if label == 0 else 0 for label in data['y']])

y_0 = np.reshape(y_0, (rows, 1))

X.shape, y_0.shape, theta.shape, all_theta.shape

> ((5000L, 401L), (5000L, 1L), (401L,), (10L, 401L))

注意,theta是一维数组,所以当它被转换为计算梯度的代码中的矩阵时,它变成一个(1×401)矩阵。 我们还要检查y中的类标签,以确保它们看起来像我们期望的。

np.unique(data['y'])

> array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=uint8)

确保函数正常运行,并获得一些合理的输出。

all_theta = one_vs_all(data['X'], data['y'], 10, 1)

all_theta

array([[ -5.79312170e+00, 0.00000000e+00, 0.00000000e+00, ...,

1.22140973e-02, 2.88611969e-07, 0.00000000e+00],

[ -4.91685285e+00, 0.00000000e+00, 0.00000000e+00, ...,

2.40449128e-01, -1.08488270e-02, 0.00000000e+00],

[ -8.56840371e+00, 0.00000000e+00, 0.00000000e+00, ...,

-2.59241796e-04, -1.12756844e-06, 0.00000000e+00],

...,

[ -1.32641613e+01, 0.00000000e+00, 0.00000000e+00, ...,

-5.63659404e+00, 6.50939114e-01, 0.00000000e+00],

[ -8.55392716e+00, 0.00000000e+00, 0.00000000e+00, ...,

-2.01206880e-01, 9.61930149e-03, 0.00000000e+00],

[ -1.29807876e+01, 0.00000000e+00, 0.00000000e+00, ...,

2.60651472e-04, 4.22693052e-05, 0.00000000e+00]])

最后一步是使用训练过的分类器预测每个图像的标签。对于这一步骤,对于每个训练实例(使用矢量化代码),我们将计算每个类的类概率,并将输出类标签分配给具有最高概率的类。

def predict_all(X, all_theta):

rows = X.shape[0]

params = X.shape[1]

num_labels = all_theta.shape[0]

# same as before, insert ones to match the shape

X = np.insert(X, 0, values=np.ones(rows), axis=1)

# convert to matrices

X = np.matrix(X)

all_theta = np.matrix(all_theta)

# compute the class probability for each class on each training instance

h = sigmoid(X * all_theta.T)

# create array of the index with the maximum probability

h_argmax = np.argmax(h, axis=1)

# because our array was zero-indexed we need to add one for the true label prediction

h_argmax = h_argmax + 1

return h_argmax

现在我们可以使用predict_all函数为每个实例生成类预测,并了解分类器的工作情况。

y_pred = predict_all(data['X'], all_theta)

correct = [1 if a == b else 0 for (a, b) in zip(y_pred, data['y'])]

accuracy = (sum(map(int, correct)) / float(len(correct)))

print 'accuracy = {0}%'.format(accuracy * 100)

> accuracy = 97.58%

接近98%,相当不错,逻辑回归是一个相对简单的方法。

python多元逻辑回归_Python机器学习的练习四:多元逻辑回归相关推荐

  1. python多元线性回归实例_Python机器学习多元线性回归模型 | kTWO-个人博客

    前言 在上一篇文章<机器学习简单线性回归模型>中我们讲解分析了Python机器学习中单输入的线性回归模型,但是在实际生活中,我们遇到的问题都是多个条件决定的问题,在机器学习中我们称之为多元 ...

  2. python分类算法报告_Python机器学习(1)——决策树分类算法

    1.决策树算法 决策树用树形结构对样本的属性进行分类,是最直观的分类算法,而且也可以用于回归.不过对于一些特殊的逻辑分类会有困难.典型的如异或(XOR)逻辑,决策树并不擅长解决此类问题. 决策树的构建 ...

  3. 机器学习实战(四)逻辑回归LR(Logistic Regression)

    目录 0. 前言 1. Sigmoid 函数 2. 梯度上升与梯度下降 3. 梯度下降法(Gradient descent) 4. 梯度上升法(Gradient ascent) 5. 梯度下降/上升法 ...

  4. python svr回归_python机器学习库scikit-learn:SVR的基本应用

    scikit-learn是python的第三方机器学习库,里面集成了大量机器学习的常用方法.例如:贝叶斯,svm,knn等. scikit-learn的官网 : http://scikit-learn ...

  5. python 多分类逻辑回归_机器学习实践:多分类逻辑回归(softmax回归)的sklearn实现和tensorflow实现...

    本文所有代码及数据可下载. Scikit Learn 篇:Light 版 scikit learn内置了逻辑回归,对于小规模的应用较为简单,一般使用如下代码即可 from sklearn.linear ...

  6. 机器学习算法(四)逻辑回归理论与python实现+经典示例(从疝气病预测病马的死亡率)

    学习笔记更新 什么是逻辑回归? 简要介绍     逻辑回归是用来解决线性回归问题的,它将线性回归得到的结果通过逻辑函数映射到[0,1]之间,因此称逻辑回归.逻辑回归模型主要用于解决二分类问题,是一个分 ...

  7. python多元回归预测例子_Python机器学习,多元线性回归分析问题

    @Author:润森,Runsen,公众号:润森笔记 什么是多元线性回归 在回归分析中,如果有两个或两个以上的自变量,就称为多元回归.**事实上,一种现象常常是与多个因素相联系的,由多个自变量的最优组 ...

  8. python实现岭回归_python机器学习:岭回归介绍

    接着上节讨论,岭回归也是一种用于回归的线性模型,因此它的预测公式与普通的最小二乘法相同.但在岭回归中,对系数(w)的选择不仅要在训练数据上得到好的预测结果,而且要拟合附加约束.同时我们还希望系数尽量小 ...

  9. python线性回归算法简介_Python机器学习(二):线性回归算法

    机器学习研究的问题分为分类问题和回归问题.分类问题很好理解,而回归问题就是找到一条曲线,可以最大程度地拟合样本特征和样本输出标记之间的关系.当给算法一个输入时,这条曲线可以计算出相应可能的输出.回归算 ...

  10. python训练模型测试模型_python 机器学习中模型评估和调参

    在做数据处理时,需要用到不同的手法,如特征标准化,主成分分析,等等会重复用到某些参数,sklearn中提供了管道,可以一次性的解决该问题 先展示先通常的做法 import pandas as pd f ...

最新文章

  1. 35.2. Subversion 版本控制
  2. C#方法中参数ref和out的解析
  3. c语言字符串67ASDSff,(指针编程题目.doc
  4. variable `xxx' has initializer but incomplete type
  5. 李宏毅机器学习课程-Transfer Learning
  6. bzoj1231 [Usaco2008 Nov]mixup2 混乱的奶牛——状压DP
  7. 嵌入式面试中常见的编程题目
  8. web td不对齐_珍稀干货!阿里 Web 音视频开发趟坑指南
  9. NumPy Beginner's Guide 2e 带注释源码 六、深入 NumPy 模块
  10. sql date时间加减几天几小时
  11. labview与威纶通触摸屏ftp通讯
  12. WordPress主题 Modown V3.0+Erphpdown9.7.1虚拟素材资源付费下载响应式主题网站模板
  13. RK平台HDMI、喇叭音频同时输出
  14. 学习java 的第一节课
  15. 高项 人力资源管理论文
  16. 移动硬盘插到电脑后显示在设备和打印机解决办法
  17. 感谢牛健老师为《Spring Boot实战派》开源Fadmin
  18. 内边距和外边距,清除默认的内外边距
  19. 异常解决:java.lang.IllegalStateException: Failed to introspect Class
  20. wt概述-c++ web

热门文章

  1. [转载]工作5年的回顾,即成长历程
  2. 电脑桌面简约时钟工具OneClock
  3. 读书笔记(一)数联网——大数据如何互联
  4. 寂寞沙洲冷c语言程序,周传雄《寂寞沙洲冷》吉他谱简单版 酷音小伟吉他弹唱教学吉他谱...
  5. 运算放大器的基本电路符号
  6. matlab plotyy 横坐标,MATLAB中plotyy函数详解:matlab双Y轴作图
  7. 研发流程中的产品测试
  8. python 列表 元组_python基础:元组(tuple)列表(list)介绍
  9. Zap之日志记录器选择
  10. 23种设计模式极速记忆法(全网独一无二)