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并不会要求数据完全线性可分. 但是现实生活中有大量的非 ...
随机推荐
- Http协议Content-Length详解
前言 http协议是互联网中最重要的协议之一,虽然看上去很简单,但是实际中经常遇到问题,我们就已经遇到好几次了.有长连接相关的,有报文解析相关的.对http协议不能一知半解,必须透彻理解才行.本文通过 ...
- 关于MySQL的经典例题50道
--1.学生表Student(S,Sname,Sage,Ssex) --S 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别--2.课程表 Course(C,Cname,T) - ...
- k8s中负载均衡器【ingress-nginx】部署
在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的.为了使外部的应用能够访问集群内的服务,在Kubernetes 目前 提供了以下几种方案: Node ...
- 04-09 XgBoost算法
目录 XgBoost算法 一.XgBoost算法学习目标 二.XgBoost算法详解 2.1 XgBoost算法参数 2.2 XgBoost算法目标函数 2.3 XgBoost算法正则化项 2.4 X ...
- Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 10.x
运行Reac项目报: Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js ...
- Windows快捷方式绑马
0x01前言 windows的shell32在处理控制面板程序的快捷方式文件时,存在一个漏洞,可以加载硬盘上的任意DLL文件,即可执行任意代码. 之前看到一款俄罗斯黑阔写的的快捷方式下载木马并运行的生 ...
- 关于git提交
16年申请注册的git账号,除了需要找一些有用的demo时会逛一下,其实一直没拿起来真实用过. 好了,说一下今天下午呕心沥血弄出来的东西,其实就是简单的用git小黑窗口推文件夹上去,本人较笨,会按照我 ...
- spring boot 中通过CORS实现跨域
一.跨域问题出现的原因 出现跨域问题的原因是同源策略. 同源策略 主要是三同:同协议.同域名.同端口, 同源策略目的 保证用户信息安全,防止恶意网站窃取数据.同源策略是必须的,否则cookie可以共享 ...
- 将 so|JNI|NDK 之间的关系说明白
最近在了解公司历史的发展,发现了公司产品中几乎都要使用 so 文件,不禁好奇这个 so 到底是何方神圣. so 文件 so 是 shared object 的缩写,见名思义就是共享的对象,机器可以直接 ...
- javascript学习总结之对象的深拷贝和浅拷贝
前言 最近在写ES6的文章的时候发现重复遇到关于javascript深拷贝和浅拷贝的问题,然后查找了一些资料,根据资料和自己的理解做了以下笔记,毕竟javascript关于深拷贝和浅拷贝的问题在一些面 ...