客户端码农学习ML —— 用TensorFlow实现线性回归算法

简介: 线性回归(Linear Regression) 线性回归算法是机器学习、统计分析中重要的算法之一,也是常用的相对简单的算法。 微信小游戏跳一跳某辅助程序wechat jump game,之前要事先根据屏幕尺寸填写一个按压时间与弹跳距离的比例经验值并不断人为调整,后来可通过此算法拟合按压时间与弹跳距离了, Pull Request在此。

线性回归(Linear Regression)

线性回归算法是机器学习、统计分析中重要的算法之一,也是常用的相对简单的算法。

微信小游戏跳一跳某辅助程序wechat jump game,之前要事先根据屏幕尺寸填写一个按压时间与弹跳距离的比例经验值并不断人为调整,后来可通过此算法拟合按压时间与弹跳距离了, Pull Request在此

给定由d个属性描述的点集X=(x1;x2;...;xd), 线性模型试图学得一个通过属性的线性组合来进行预测的函数,即ƒ(x)=w1x1 + w2x2 + ... + wdxd + b,知道w和b后就能确定模型。

原理

我们在高中数学中已经学过只有一个属性x求待定系数的算法,即最小二乘法,一系列离散点通过最小二乘法即可确定一条回归直线ƒ(x)=kx+b,这种只有一个输入变量/特征值的问题也叫作单变量线性回归问题。

Cost Function

不同的k值,也使得预测值与实际值的建模误差不同,方差是常用的一种损失函数,也叫代价函数(Cost Function),我们的目标就是找到可以使得方差最小的模型参数。

单变量线性回归的损失函数通图形化后常类似于一个抛物线,有一个最小值。

ai_cost_parabola

两个变量/特征的线性回归损失函数图形化后类似于一个碗,碗底就是最小值。

ai_cost_bowl

更多特征值的情况下,高维空间难以图形化,损失函数在不同区域有不同的极值,一般较难计算出最小值。

Gradient Descent

我们通常采用梯度下降算法来求的这个最小值。先随机选择一个参数组合,计算损失函数,然后找下一个能让损失函数下降最多的新参数组合并同步更新,继续这么做直到找到一个局部最小值。不同的初始参数组合可能会找到不同的局部最小值。

ai_cost_gradient_descent1

梯度下降算法公式:

ai_cost_gradient_descent2

其中α是学习率(learning rate),α决定了沿着使得损失函数下降较大的方向迈出的步子有多大,值太小则收敛太慢,值太大则可能越过最小值,导致无法收敛或者无法找到合理的待定参数组合θ。

ai_cost_gradient_descent3

α右边是一个导数项,需要导数、偏导数的基础知识,简单来讲就是通过当前θ处的切线斜率来决定正确的方向,并配合学习率决定走多远。

我们现在用TensorFlow实现并体验下机器学习的思想。

准备数据

首先通过numpy生成一些模拟数据并有意随机偏移点(xi,yi),把生成的随机点当做数据集,并把数据集按照8:2的比例分成训练集与测试集,然后通过代码去读取训练集并更新欲求参数k、b,使得k、b越来越接近真实值,使得f(xi)≈yi,从而使得方差最小。

方差对应了欧几里得距离,最小二乘法就是试图找到一条直线,使所有样本到直线上的欧氏距离之和最小。

import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
import matplotlib.pyplot as plt

ops.reset_default_graph()

sess = tf.Session()

data_amount = 101 # 数据数量
batch_size = 25 # 批量大小

# 造数据 y=Kx+3 (K=5)
x_vals = np.linspace(20, 200, data_amount)

y_vals = np.multiply(x_vals, 5)
y_vals = np.add(y_vals, 3)

# 生成一个N(0,15)的正态分布一维数组
y_offset_vals = np.random.normal(0, 15, data_amount)
y_vals = np.add(y_vals, y_offset_vals) # 为了有意使的y值有所偏差

模型训练

# 创建占位符
x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)

# 构造K 就是要训练得到的值
K = tf.Variable(tf.random_normal(mean=0, shape=[1, 1]))

calcY = tf.add(tf.matmul(x_data, K), 3)

# 真实值与模型估算的差值
loss = tf.reduce_mean(tf.square(y_target - calcY))

init = tf.global_variables_initializer()
sess.run(init)

my_opt = tf.train.GradientDescentOptimizer(0.0000005)
train_step = my_opt.minimize(loss) # 目的就是使损失值最小

loss_vec = [] #保存每次迭代的损失值,为了图形化

for i in range(1000):
    rand_index = np.random.choice(data_amount, size=batch_size)
    x = np.transpose([x_vals[rand_index]])
    y = np.transpose([y_vals[rand_index]])
    sess.run(train_step, feed_dict={x_data: x, y_target: y})

    tmp_loss = sess.run(loss, feed_dict={x_data: x, y_target: y})
    loss_vec.append(tmp_loss)
# 每25的倍数输出往控制台输出当前训练数据供查看进度
    if (i + 1) % 25 == 0:
        print('Step #' + str(i + 1) + ' K = ' + str(sess.run(K)))
        print('Loss = ' + str(sess.run(loss, feed_dict={x_data: x, y_target: y})))

# 当训练完成后k的值就是当前的得到的结果,可以通过sess.run(K)取得
sess.close()

学习框架会使用梯度下降法去寻找一个最优解, 使得方差最小。

学习率是个很重要的参数,如果过小,算法收敛耗时很长,如果过大,可能结果不收敛或者直接NAN无法得到结果。

展示结果

本次试验用到了numpy及matplot,后续再练习下这两个库的使用,加强下印象。

best_fit = []
for i in x_vals:
    best_fit.append(KValue * i + 3)

plt.plot(x_vals, y_vals, 'o', label='Data')
plt.plot(x_vals, best_fit, 'r-', label='Base fit line')
# plt.plot(loss_vec, 'k-')
plt.title('Batch Look Loss')
plt.xlabel('Generation')
plt.ylabel('Loss')
plt.show()

图形化后有两张图,一张表示本次训练最后拟合直线,一张表示每次训练损失值的收敛情况,但结果不是唯一的。

ai_kai_line_only_mul_batch_line

ai_kai_line_only_mul_batch_loss

可以看出,随着训练的进行,预测损失整体越来越小,改变学习率或者批量大小则会使训练损失收敛速度发生显著变化,甚至无法收敛,总体上批量数值越大效果越好。

其他回归算法

除了线性回归算法,还有其它好几种回归算法,后续陆续学习、补充。

戴明回归算法

最小二乘线性回归算法是最小化到回归直线的竖直距离,只考虑y值,而戴明回归算法是最小化到回归直线垂直距离,同时考虑x值与y值。

具体算法修改下相减的损失函数即可,两者计算结果基本一致。

lasso回归与岭回归算法

主要是在公式中增加正则项来限制斜率,lasso回归增加L1正则项,岭回归增加L2正则项。

弹性网络回归算法

综合lasso回归和岭回归的一种算法,在损失函数中同时增加L1和L2正则项。

逻辑回归算法

将线性回归转换成一个二值分类器,通过sigmoid函数将线性回归的输出缩放到0、1之间,判断目标是否属于某一类。

参考

http://qianhk.com/2018/02/客户端码农学习ML-用TensorFlow实现线性回归算法/

http://studentdeng.github.io/blog/2014/07/28/machine-learning-tutorial/

本文首发于钱凯凯的博客

 

目录
相关文章
|
7天前
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
11天前
|
XML JavaScript 前端开发
学习react基础(1)_虚拟dom、diff算法、函数和class创建组件
本文介绍了React的核心概念,包括虚拟DOM、Diff算法以及如何通过函数和类创建React组件。
15 2
|
25天前
|
存储 算法 测试技术
预见未来?Python线性回归算法:数据中的秘密预言家
【9月更文挑战第11天】在数据的海洋中,线性回归算法犹如智慧的预言家,助我们揭示未知。本案例通过收集房屋面积、距市中心距离等数据,利用Python的pandas和scikit-learn库构建房价预测模型。经过训练与测试,模型展现出较好的预测能力,均方根误差(RMSE)低,帮助房地产投资者做出更明智决策。尽管现实关系复杂多变,线性回归仍提供了有效工具,引领我们在数据世界中自信前行。
45 5
|
2月前
|
机器学习/深度学习 人工智能 资源调度
【博士每天一篇文献-算法】连续学习算法之HAT: Overcoming catastrophic forgetting with hard attention to the task
本文介绍了一种名为Hard Attention to the Task (HAT)的连续学习算法,通过学习几乎二值的注意力向量来克服灾难性遗忘问题,同时不影响当前任务的学习,并通过实验验证了其在减少遗忘方面的有效性。
49 12
|
2月前
|
机器学习/深度学习 人工智能 算法
【人工智能】线性回归模型:数据结构、算法详解与人工智能应用,附代码实现
线性回归是一种预测性建模技术,它研究的是因变量(目标)和自变量(特征)之间的关系。这种关系可以表示为一个线性方程,其中因变量是自变量的线性组合。
50 2
|
2月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
2月前
|
算法 NoSQL 中间件
go语言后端开发学习(六) ——基于雪花算法生成用户ID
本文介绍了分布式ID生成中的Snowflake(雪花)算法。为解决用户ID安全性与唯一性问题,Snowflake算法生成的ID具备全局唯一性、递增性、高可用性和高性能性等特点。64位ID由符号位(固定为0)、41位时间戳、10位标识位(含数据中心与机器ID)及12位序列号组成。面对ID重复风险,可通过预分配、动态或统一分配标识位解决。Go语言实现示例展示了如何使用第三方包`sonyflake`生成ID,确保不同节点产生的ID始终唯一。
go语言后端开发学习(六) ——基于雪花算法生成用户ID
|
2月前
|
存储 机器学习/深度学习 算法
【博士每天一篇文献-算法】连续学习算法之HNet:Continual learning with hypernetworks
本文提出了一种基于任务条件超网络(Hypernetworks)的持续学习模型,通过超网络生成目标网络权重并结合正则化技术减少灾难性遗忘,实现有效的任务顺序学习与长期记忆保持。
34 4
|
2月前
|
存储 机器学习/深度学习 算法
【博士每天一篇文献-算法】连续学习算法之RWalk:Riemannian Walk for Incremental Learning Understanding
RWalk算法是一种增量学习框架,通过结合EWC++和修改版的Path Integral算法,并采用不同的采样策略存储先前任务的代表性子集,以量化和平衡遗忘和固执,实现在学习新任务的同时保留旧任务的知识。
74 3
|
17天前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
在数据驱动时代,Python凭借简洁的语法和强大的库支持,成为数据分析与机器学习的首选语言。Pandas和NumPy是Python数据分析的基础,前者提供高效的数据处理工具,后者则支持科学计算。TensorFlow与PyTorch作为深度学习领域的两大框架,助力数据科学家构建复杂神经网络,挖掘数据深层价值。通过Python打下的坚实基础,结合TensorFlow和PyTorch的强大功能,我们能在数据科学领域探索无限可能,解决复杂问题并推动科研进步。
38 0
下一篇
无影云桌面