最近看到了一个系列博客,写的不错,就拿来学习了下。一来加深理解,二来锻炼自己编写代码的能力。

关于基础的理论知识就不重述了,网上资源很多,这里推荐:https://www.zybuluo.com/hanbingtao/note/448086,因为我就是学习的这个系列博客。

这里只对比和上篇python 实现感知器之间的联系和代码复用的地方。
这里只更新下激活函数即可,而且这里的激活函数相当于什么也没做,原样输出,即保持线性的形式。

代码如下:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-from perceptron import Perceptron#定义激活函数f
f = lambda x: x # 相当于原样输出class LinearUnit(Perceptron):def __init__(self, input_num):'''初始化线性单元,设置输入参数的个数'''Perceptron.__init__(self, input_num, f)def get_training_dataset():'''捏造5个人的收入数据'''# 构建训练数据# 输入向量列表,每一项是工作年限input_vecs = [[5], [3], [8], [1.4], [10.1]]# 期望的输出列表,月薪,注意要与输入一一对应labels = [5500, 2300, 7600, 1800, 11400]return input_vecs, labels    def train_linear_unit():'''使用数据训练线性单元'''# 创建感知器,输入参数的特征数为1(工作年限)lu = LinearUnit(1)# 训练,迭代10轮, 学习速率为0.01input_vecs, labels = get_training_dataset()lu.train(input_vecs, labels, 10, 0.01)#返回训练好的线性单元return ludef plot(linear_unit):import matplotlib.pyplot as pltinput_vecs, labels = get_training_dataset()fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(map(lambda x: x[0], input_vecs), labels)# 训练得到权重和偏置weights = linear_unit.weightsbias = linear_unit.biasx = range(0,12,1)y = map(lambda x:weights[0] * x + bias, x)ax.plot(x, y)plt.show()if __name__ == '__main__': '''训练线性单元'''linear_unit = train_linear_unit()# 打印训练获得的权重print linear_unit# 测试print 'Work 3.4 years, monthly salary = %.2f' % linear_unit.predict([3.4])print 'Work 15 years, monthly salary = %.2f' % linear_unit.predict([15])print 'Work 1.5 years, monthly salary = %.2f' % linear_unit.predict([1.5])print 'Work 6.3 years, monthly salary = %.2f' % linear_unit.predict([6.3])plot(linear_unit)

运行结果:

weights :[1124.0634970262222]
bias    :85.485289Work 3.4 years, monthly salary = 3907.30
Work 15 years, monthly salary = 16946.44
Work 1.5 years, monthly salary = 1771.58
Work 6.3 years, monthly salary = 7167.09

模型很简单,激活函数和学习算法也很简单,但这里我觉得最大的值得学习的地方就在于面向对象编程范式的便利。

这里导入了Perceptron类:

# 这里定义一个感知器的类
class Perceptron(object):def __init__(self, input_num, activator):'''初始化感知器,设置输入参数的个数,以及激活函数。激活函数的类型为double -> double'''self.activator = activator# 权重向量初始化为0.0self.weights = [0.0 for _ in range(input_num)]# 偏置项初始化为0.0self.bias = 0.0def __str__(self): # __str__:类实例字符串化函数'''打印学习到的权重、偏置项'''return 'weights\t:%s\nbias\t:%f\n' % (self.weights, self.bias)def predict(self, input_vec):'''输入向量,输出感知器的计算结果'''# 把input_vec[x1,x2,x3...]和weights[w1,w2,w3,...]打包在一起# 变成[(x1,w1),(x2,w2),(x3,w3),...]# 然后利用map函数计算[x1*w1, x2*w2, x3*w3]# 最后利用reduce求和:reduce()还可以接收第3个可选参数,作为计算的初始值xi_wi=map(lambda (x, w): x * w,zip(input_vec, self.weights))# 激活函数的输入为w_1*x_1+w_2*x_2+biasreturn self.activator(reduce(lambda a, b: a + b,xi_wi , 0.0) + self.bias)def train(self, input_vecs, labels, iteration, rate):'''输入训练数据:一组向量、与每个向量对应的label;以及训练轮数、学习率'''# 每次迭代都把所有的样本输入for i in range(iteration):self._one_iteration(input_vecs, labels, rate)def _one_iteration(self, input_vecs, labels, rate):'''一次迭代,把所有的训练数据过一遍'''# 把输入和输出打包在一起,成为样本的列表[(input_vec, label), ...]# 而每个训练样本是(input_vec, label)samples = zip(input_vecs, labels)# 对每个样本,按照感知器规则更新权重for (input_vec, label) in samples:# 计算感知器在当前权重下的输出output = self.predict(input_vec)# 更新权重self._update_weights(input_vec, output, label, rate)def _update_weights(self, input_vec, output, label, rate):'''按照感知器规则更新权重'''# 把input_vec[x1,x2,x3,...]和weights[w1,w2,w3,...]打包在一起# 变成[(x1,w1),(x2,w2),(x3,w3),...]# 然后利用感知器规则更新权重delta = label - outputself.weights = map(lambda (x, w): w + rate * delta * x,zip(input_vec, self.weights))# 更新biasself.bias += rate * delta

而该类定义了

  • 初始化:初始化权重、偏置、激活函数;
  • 打印输出函数:打印学习到的权重和偏置
  • 训练参数的类方法
  • 预测的类方法
  • 一次迭代的类方法(随机梯度下降)
  • 更新参数的类方法

其中参数更新的递推公式是:

wnew=wold+η∑i=1n(y(i)−yˆ)x(i)wnew=wold+η∑i=1n(y(i)−y^)x(i)

w_{new}=w_{old}+\eta \sum _{i=1}^{n}({y^{(i)}-\widehat{y}})x^{(i)}
这里的更新方式是批梯度下降,但算法里采用的是随机梯度下降,更新公式为:

wnew=wold+η(y(i)−yˆ)x(i)wnew=wold+η(y(i)−y^)x(i)

w_{new}=w_{old}+\eta ({y^{(i)}-\widehat{y}})x^{(i)}

注意:
Python中lambda表达式
看几个例子

>>> fun = lambda x,y,z : x + y + z
>>> fun(1, 2, 3)
6
>>> fun = [(lambda n : i + n) for i in range(10)]
>>> fun
[<function <lambda> at 0x0000000002A43CF8>, <function <lambda> at 0x0000000006372DD8>, <function <lambda> at 0x0000000006372E48>, <function <lambda> at 0x0000000006372EB8>, <function <lambda> at 0x0000000006372F28>, <function <lambda> at 0x0000000006372F98>, <function <lambda> at 0x000000000637A048>, <function <lambda> at 0x000000000637A0B8>, <function <lambda> at 0x000000000637A128>, <function <lambda> at 0x000000000637A198>]
>>> fun[3](4) # fun[3](4)指调用fun中第三个函数,n赋值为3,所以结果为13
13
>>> fun[4](4)
13>>> fun = [(lambda n,i = i : i + n) for i in range(10)]
>>> fun[3](4)
7
>>> fun[4](4)
8
>>> filter(lambda x : x % 2 == 0, range(10))
[0, 2, 4, 6, 8]
>>> map(lambda x, y : x * y, range(1,4), range(1,4))
[1, 4, 9]
>>> reduce(lambda x, y : x + y, range(10))
45
>>> 

map(lambda (x, w): x * w,zip(input_vec, self.weights))的用法
首先这里的lambda (x, w): x * w,zip(input_vec, self.weights)中的lambda (x, w)的用法要注意,这里代表的是一个参数。而正确的lmbda参数形式其实是这样的lambda x,y:x+y,x,y是它的2个形参,所以这里 lambda (x,w)其实就只有一个参数,那就是一个tuple类型的参数。
看几个例子:

In [2]: map(lambda (x, w): x * w,[(2,4),(3,6)])
Out[2]: [8, 18]In [3]: map(lambda x, w: x * w,(2,4),(3,6))
Out[3]: [6, 24]In [4]: map(lambda (x, w): x * w,[(2,4),(3,6)])
Out[4]: [8, 18]In [5]: map(lambda x, w: x * w,[(2,4),(3,6)])
Traceback (most recent call last):File "<ipython-input-5-aec2dcefae36>", line 1, in <module>map(lambda x, w: x * w,[(2,4),(3,6)])TypeError: <lambda>() takes exactly 2 arguments (1 given)In [7]: map(lambda x, w: x * w,[2,4],[3,6])
Out[7]: [6, 24]

面向对象编程。面向对象是特别好的管理复杂度的工具,应对复杂问题时,用面向对象设计方法很容易将复杂问题拆解为多个简单问题,从而解救我们的大脑。
还有就是numpy实现了很多基础算法,对于实现机器学习算法来说是个必备的工具,这里没有使用numpy,从而对算法原理有更深入的理解。

线性拟合和梯度下降python代码实现—面向对象(二)相关推荐

  1. 【机器学习】梯度下降 (python代码)

    梯度下降 (python代码) 文章介绍 1.前提 2.代码实现 文章介绍 文章配图来自网络 个人学习笔记,推荐直接买课去学习 得懂python,本文代码可直接跑,环境基于[ PyCharm 2022 ...

  2. 基于python的梯度下降法的实现代码

    基于python的梯度下降法的实现 代码: def _numerical_gradient_no_batch(f, x):h = 1e-4 # 0.0001grad = np.zeros_like(x ...

  3. 零基础入门深度学习 | 第二章:线性单元和梯度下降

    北京 | 高性能计算之GPU CUDA课程11月24-26日3天密集学习 快速带你晋级阅读全文> 无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作 ...

  4. 大白话5分钟带你走进人工智能-第十一节梯度下降之手动实现梯度下降和随机梯度下降的代码(6)...

                                第十一节梯度下降之手动实现梯度下降和随机梯度下降的代码(6) 我们回忆一下,之前咱们讲什么了?梯度下降,那么梯度下降是一种什么算法呢?函数最优化 ...

  5. 读书笔记:求函数梯度的Python代码 numerical_gradient.py ← 斋藤康毅

    由多元函数全部变量的偏导数汇总而成的向量称为梯度(gradient). 梯度指示的方向是各点处的函数值减小最多的方向. 下文给出了求函数  的梯度的 Python 代码. [求函数梯度的Python代 ...

  6. 随机梯度下降python_(史上最详细)批量梯度下降算法、随机梯度下降算法、小批量梯度下降算法python代码实现...

    伪代码: 批量梯度下降法(Batch Gradient Descent): Repeat until convergence{ } 随机梯度下降法(Stochastic Batch Gradient ...

  7. python过拟合_梯度下降、过拟合和归一化

    好的课程应该分享给更多人:,点开任意一个之后会发现他们会提供系列课程整合到一起的百度网盘下载地址,包括视频+代码+资料,免费的优质资源.当然,现在共享非常多,各种mooc.博客.论坛等,很容易就可以找 ...

  8. 梯度下降python编程实现_【机器学习】线性回归——单变量梯度下降的实现(Python版)...

    [线性回归] 如果要用一句话来解释线性回归是什么的话,那么我的理解是这样子的:**线性回归,是从大量的数据中找出最优的线性(y=ax+b)拟合函数,通过数据确定函数中的未知参数,进而进行后续操作(预测 ...

  9. 零基础入门深度学习(2) - 线性单元和梯度下降

    python深度学习大全 原文地址:https://www.zybuluo.com/hanbingtao/note/448086 往期回顾 在上一篇文章中,我们已经学会了编写一个简单的感知器,并用它来 ...

最新文章

  1. Centos 安装 Wireshark
  2. 你必须知道的10个提高Canvas性能技巧
  3. 3分钟学会如何调度运营海量Redis系统
  4. LUA __call
  5. 那些年,杜蕾斯紧跟热点的骚包文案有哪些?
  6. spring的jar包以及相关的API文档的下载方式
  7. oracle调度不见了,Oracle作业job 没有自动调度起来
  8. android 5.0.1 libdvm.so,Android逆向进阶—— 脱壳的奥义(基ART模式下的dump)
  9. JavaScript中的元素获取与操作
  10. 苹果零售店每平方英尺能创造4000美元
  11. Bailian2909 字符串加空格【指针】
  12. 欧盟ETSI关于汽车雷达的规定
  13. WinForm中的NotifyIcon控件的使用
  14. Matlab绘制跳动的心
  15. 百度api验证码识别
  16. 网站性能优化之DNS Prefetch
  17. 逆天神器!“国外“最新版本,直接一键破解所有WiFi密码,傻眼了!
  18. 复现CLOCs中spconv v1.0 (commit 8da6f96)踩坑记录
  19. 实现一个简单的计算器,输入一个包含圆括号、加减乘除、求余等符号组成的算术表达式字符串,输出该算术表达式的值
  20. Android开发入门与实战之Android应用安装卸载

热门文章

  1. OpenCV均值漂移的跟踪mean-shift based tracking的实例(附完整代码)
  2. C++xor cipher异或密码算法(附完整源码)
  3. C语言实现了一个顺序栈(附完整源码)
  4. STL常用的拷贝和替换算法
  5. 经典C语言程序100例之八六
  6. k8s pod里访问不到外部ip_K8S中的Service的存在理由
  7. 04_pandas字符串函数;数据合并concat、merge;分组groupby;Reshaping;Pivot tables;时间处理(date_range、tz_localize等)
  8. 01_学习java WEB涉及到的相关技术
  9. Oracle实例和服务知识点
  10. 处理字符串_8_判断字符串含有汉字