python机器学习——自适应线性神经元
上篇博客我们说了感知器,这篇博客主要记录自适应线性神经元的实现算法及一些其他的训练细节,自适应线性神经元(简称为Adaline)由Bernard Widrow和他的博士生Tedd Hoff提出,对感知器算法进行了改进。
当然Adaline对输入向量x的处理和感知器是一样的,都是使用一个权重向量w与x线性组合后得到z,再使用激活函数将z压缩到二元输入(1/-1),区别在于Adaline使用梯度下降法来更新w。
因为我们的目的是准确分类,那么我们需要来衡量分类效果的好坏,在这里我们介绍目标函数:
\[
J(w) = \frac12 \sum_i^n(y^i - \phi(z^i))^2
\]
它也可以叫做损失函数,通过上式我们可以大致理解为什么叫做损失函数,此函数可以计算出所有训练样本的真实值和预测值之间的误差平方和(Sum of Squared Errors,简称SSE),式子前面的那个1/2是为了之后求导方便添加的,没有其他意义。
有了损失函数,于是我们的目的更具体一点,就是为了选择合适的w,使损失函数取得最小值,损失函数越小,就意味着错误分类的情况越少,算法的分类效果也就越好。而因为Adaline的损失函数是一个凸函数,所以我们可以使用梯度下降来找到使损失函数取值最小的权重向量w,我们可以想象为一个小球滚下山:
刚开始的w也许会得到一个很大的损失函数,但是由于损失函数J是w的函数,并且也是一个凸函数,它存在一个最小值,学过微积分的朋友应该知道,要找到一个函数的最值,一般的方法通过求导并使导数为零,解出的那个x就是最值,在这里的梯度下降也就是求导,但由于w是一个权重向量,是多维的,所以需要损失函数对w求偏导,得到w中每个分量的偏导数,然后再更新整个w,具体的推导过程如下:
\[
注意:w为向量,w_j为向量w中的某一分量\\w = w + \Delta w\\\Delta w = -\eta\Delta J(w)\\\frac{\partial J}{\partial w_j} = \frac{\partial }{\partial w_j} \frac 12 \sum_i(y^i-\phi(z^i))^2 \\= \frac 12 \frac{\partial }{\partial w_j} \sum_i(y^i-\phi(z^i))^2 \\= \frac 12 \sum_i2(y^i-\phi(z^i)) \frac{\partial }{\partial w_j}(y^i-\phi(z^i))\\= \sum_i(y^i-\phi(z^i))\frac{\partial }{\partial w_j}(y^i-\sum_i(w_j^ix_j^i))\\=\sum_i(y^i-\phi(z^i))(-x_j^i)\\=-\sum_i(y^i-\phi(z^i))x_j^i\\所以\Delta w_j = -\eta\frac{\partial J}{\partial w_j}=\eta\sum_i(y^i-\phi(z^i))x_j^i
\]
一点要注意所以的权重向量w中的分量是同时更新的,而且每次更新都用到了所有的训练样本,所以梯度下降法也被称为批量梯度下降(batch gradient descent)
接下来我们具体来实现自适应线性神经元,由于和感知机的学习规则很相似,所以直接在感知器的基础上进行修改得到,其中需要修改fit方法,因为在这里我们要使用梯度下降算法。
class AdalineGD(object):
"""ADAptive LInear NEuron classifier.
Parameters
----------
eta:float
Learning rate(between 0.0 and 1.0
n_iter:int
Passes over the training dataset.
Attributes
----------
w_:1d-array
weights after fitting.
errors_:list
Number of miscalssifications in every epoch.
"""
def __init__(self, eta=0.01, n_iter=10):
self.eta = eta
self.n_iter = n_iter
def fit(self, X, y):
"""Fit training data.
:param X:{array-like}, shape=[n_samples, n_features]
Training vectors,
:param y: array-like, shape=[n_samples]
Target values.
:return:
self:object
"""
self.w_ = np.zeros(1 + X.shape[1]) # Add w_0
self.cost_ = []
for i in range(self.n_iter):
output = self.net_input(X)
errors = (y - output)
self.w_[1:] += self.eta * X.T.dot(errors)
self.w_[0] += self.eta * errors.sum()
cost = (errors ** 2).sum() / 2.0
self.cost_.append(cost)
return self
def net_input(self, X):
"""Calculate net input"""
return np.dot(X, self.w_[1:]) + self.w_[0]
def activation(self, X):
"""Computer linear activation"""
return self.net_input(X)
def predict(self, X):
"""Return class label after unit step"""
return np.where(self.activation(X) >= 0.0, 1, -1)
分别使用不同的学习率(0.01和0.0001)训练,观察神经元学习过程。其中学习率、迭代次数我们称他们为超参数(hyperparameters),我们可以手动设置,超参数设置的是否合适对于整个训练过程都很重要。
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8,4))
ada1 = AdalineGD(n_iter=10, eta=0.01).fit(X, y)
ax[0].plot(range(1, len(ada1.cost_) + 1), np.log10(ada1.cost_), marker='o')
ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('log(Sum-squared-error)')
ax[0].set_title('Adaline - Learning rate 0.01')
ada2 = AdalineGD(n_iter=10, eta=0.0001).fit(X, y)
ax[1].plot(range(1, len(ada2.cost_) + 1), ada2.cost_, marker='o')
ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('Sum-squared-error')
ax[1].set_title('Adaline - Learning rate 0.0001')
plt.show()
可以看出,左图中学习率为0.01,随着迭代次数的增加,误差在增加,说明学习率设置的不合适,产生了很大的危害,而右图学习率为0.0001,随着迭代次数的增加,误差在减少,但是减少的过于缓慢,算法收敛的很慢,训练的效率太低,所以我们可以看出过大或过小的学习率都是不合适的。
由右图可以看出,如果学习率过大,就会导致每次梯度下降时都跳过了对应最小值的权重向量w,使得算法无法收敛。
接下来我们介绍一种数据预处理方法,在训练前将特征进行某种缩放操作,这里我们称为特征标准化,可以使所有特征数据缩放成平均值为0,方差为1,加快模型的训练速度,而且可以避免模型学习的很扭曲。
具体公式如下:
\[
x_j^, = \frac {x_j-\mu_j}{\sigma_j}
\]
具体实现如下:
X_std = np.copy(X)
X_std[:, 0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()
X_std[:, 1] = (X[:,1] - X[:,1].mean()) / X[:,1].std()
数据已经预处理结束,接下来我们开始训练模型
ada = AdalineGD(n_iter=15, eta=0.01)
ada.fit(X_std, y)
plot_decision_region(X_std, y, classifier=ada)
plt.title('Adaline - Gradient Descent')
plt.xlabel('sepal length [standardized]')
plt.ylabel('petal length [standardized]')
plt.legend(loc='upper left')
plt.show()
plt.plot(range(1, len(ada.cost_) + 1), ada.cost_, marker='o')
plt.xlabel('Epoches')
plt.ylabel('Sum-squared_error')
plt.show()
从上图看出,随着迭代次数的增加,误差逐渐降低,虽然学习率为0.01,在进行标准化之前,算法并不能收敛,但经过标准化后,算法最终收敛。
python机器学习——自适应线性神经元的更多相关文章
- 吴裕雄 python 机器学习——支持向量机线性分类LinearSVC模型
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets, linear_model,svm fr ...
- 吴裕雄 python 机器学习——局部线性嵌入LLE降维模型
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt from sklearn import datas ...
- Python机器学习中文版
Python机器学习简介 第一章 让计算机从数据中学习 将数据转化为知识 三类机器学习算法 第二章 训练机器学习分类算法 透过人工神经元一窥早期机器学习历史 使用Python实现感知机算法 基于Iri ...
- Python机器学习中文版目录
建议Ctrl+D保存到收藏夹,方便随时查看 人工智能(AI)学习资料库 Python机器学习简介 第一章 让计算机从数据中学习 将数据转化为知识 三类机器学习算法 第二章 训练机器学习分类算法 透过人 ...
- 《Python 机器学习》笔记(二)
机器学习分类算法 本章将介绍最早以算法方式描述的分类机器学习算法:感知器(perceptron)和自适应线性神经元. 人造神经元--早期机器学习概览 MP神经元 生物神经元和MP神经元模型的对应关系如 ...
- python机器学习——随机梯度下降
上一篇我们实现了使用梯度下降法的自适应线性神经元,这个方法会使用所有的训练样本来对权重向量进行更新,也可以称之为批量梯度下降(batch gradient descent).假设现在我们数据集中拥有大 ...
- Python机器学习笔记:不得不了解的机器学习知识点(2)
之前一篇笔记: Python机器学习笔记:不得不了解的机器学习知识点(1) 1,什么样的资料集不适合用深度学习? 数据集太小,数据样本不足时,深度学习相对其它机器学习算法,没有明显优势. 数据集没有局 ...
- python机器学习实战(四)
python机器学习实战(三) 版权声明:本文为博主原创文章,转载请指明转载地址 www.cnblogs.com/fydeblog/p/7364317.html 前言 这篇notebook是关于机器学 ...
- Python机器学习:5.6 使用核PCA进行非线性映射
许多机器学习算法都有一个假设:输入数据要是线性可分的.感知机算法必须针对完全线性可分数据才能收敛.考虑到噪音,Adalien.逻辑斯蒂回归和SVM并不会要求数据完全线性可分. 但是现实生活中有大量的非 ...
随机推荐
- 问题TypeError: __init__() takes 1 positional argument but 2 were given解决方案
在搭建自动化框架时,遇到一个问题,如下图: 根据报错的意思,应该是__init__函数的问题, 位置应该是HomePage文件 立马去查看一下文件,如图: 原来是因为的粗心大意__init__(sel ...
- Flask中的数据连接池
pymsql链接数据库 import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd=' ...
- python requests简单接口自动化
get方法 url:显而易见,就是接口的地址url啦 headers:定制请求头(headers),例如:content-type = application/x-www-form-urlencode ...
- Jenkins部署(基于Linux)
1.安装JDK 我不列出来了,自行百度 java -version 2.安装tomcat (1)创建目录tomcat8 (2)导入tomcat文件到tomcat8目录中并解压 (3)启动tomcat ...
- Redis高级应用解析:缓存穿透、击穿、雪崩
1 背景 像我们去面试一些大公司的时候,就会遇到一些关于缓存的问题.可能很多同学都是接触过,多多少少了解一些,但是如果没有好好记录这些内容,不熟练精通的话,在真正面试的时候,就很难答出来了. 在我们的 ...
- JavaScript七宗罪和一些槽点
当下JavaScript越来越流行,成为长期霸语言榜前三的语言.但是实际上JavaScript是一个很丑陋有很多槽点的语言,这就是为什么新出了那么多框架(从jQuery到Vue)以及海尔斯伯格大大推出 ...
- ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口
目录 ① 存储角色/用户所能访问的 API ② 实现 IAuthorizationRequirement 接口 ③ 实现 TokenValidationParameters ④ 生成 Token ⑤ ...
- 百万年薪python之路 -- 面向对象之三大特性
1.面向对象之三大特性 1.1封装 封装:就是把一堆代码和数据,放在一个空间,并且可以使用 对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封 ...
- 百万年薪python之路 -- 装饰器
装饰器 1.1 开放封闭原则 开放封闭原则具体定义是这样: 1.对扩展是开放的 我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改.所以我们必须允许代码扩展.添加新 ...
- CentOS7 下升级Python版本
来博客园的第一篇博客,以后要坚持养成记录.分享的习惯啊,这样生活才会有痕迹~ 服务器版本:CentOS 7.3 64位 旧Python版本:2.7.5 新Python版本:3.8.0 说明:本次配置使 ...