专栏首页恩蓝脚本python梯度下降算法的实现

python梯度下降算法的实现

本文实例为大家分享了python实现梯度下降算法的具体代码,供大家参考,具体内容如下

简介

本文使用python实现了梯度下降算法,支持y = Wx+b的线性回归 目前支持批量梯度算法和随机梯度下降算法(bs=1) 也支持输入特征向量的x维度小于3的图像可视化 代码要求python版本 3.4

代码

'''
梯度下降算法
Batch Gradient Descent
Stochastic Gradient Descent SGD
'''
__author__ = 'epleone'
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import sys
# 使用随机数种子, 让每次的随机数生成相同,方便调试
# np.random.seed(111111111)
class GradientDescent(object):
eps = 1.0e-8
max_iter = 1000000 # 暂时不需要
dim = 1
func_args = [2.1, 2.7] # [w_0, .., w_dim, b]
def __init__(self, func_arg=None, N=1000):
self.data_num = N
if func_arg is not None:
self.FuncArgs = func_arg
self._getData()
def _getData(self):
x = 20 * (np.random.rand(self.data_num, self.dim) - 0.5)
b_1 = np.ones((self.data_num, 1), dtype=np.float)
# x = np.concatenate((x, b_1), axis=1)
self.x = np.concatenate((x, b_1), axis=1)
def func(self, x):
# noise太大的话, 梯度下降法失去作用
noise = 0.01 * np.random.randn(self.data_num) + 0
w = np.array(self.func_args)
# y1 = w * self.x[0, ] # 直接相乘
y = np.dot(self.x, w) # 矩阵乘法
y += noise
return y
@property
def FuncArgs(self):
return self.func_args
@FuncArgs.setter
def FuncArgs(self, args):
if not isinstance(args, list):
raise Exception(
'args is not list, it should be like [w_0, ..., w_dim, b]')
if len(args) == 0:
raise Exception('args is empty list!!')
if len(args) == 1:
args.append(0.0)
self.func_args = args
self.dim = len(args) - 1
self._getData()
@property
def EPS(self):
return self.eps
@EPS.setter
def EPS(self, value):
if not isinstance(value, float) and not isinstance(value, int):
raise Exception("The type of eps should be an float number")
self.eps = value
def plotFunc(self):
# 一维画图
if self.dim == 1:
# x = np.sort(self.x, axis=0)
x = self.x
y = self.func(x)
fig, ax = plt.subplots()
ax.plot(x, y, 'o')
ax.set(xlabel='x ', ylabel='y', title='Loss Curve')
ax.grid()
plt.show()
# 二维画图
if self.dim == 2:
# x = np.sort(self.x, axis=0)
x = self.x
y = self.func(x)
xs = x[:, 0]
ys = x[:, 1]
zs = y
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs, ys, zs, c='r', marker='o')
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
else:
# plt.axis('off')
plt.text(
0.5,
0.5,
"The dimension(x.dim   2) \n is too high to draw",
size=17,
rotation=0.,
ha="center",
va="center",
bbox=dict(
boxstyle="round",
ec=(1., 0.5, 0.5),
fc=(1., 0.8, 0.8), ))
plt.draw()
plt.show()
# print('The dimension(x.dim   2) is too high to draw')
# 梯度下降法只能求解凸函数
def _gradient_descent(self, bs, lr, epoch):
x = self.x
# shuffle数据集没有必要
# np.random.shuffle(x)
y = self.func(x)
w = np.ones((self.dim + 1, 1), dtype=float)
for e in range(epoch):
print('epoch:' + str(e), end=',')
# 批量梯度下降,bs为1时 等价单样本梯度下降
for i in range(0, self.data_num, bs):
y_ = np.dot(x[i:i + bs], w)
loss = y_ - y[i:i + bs].reshape(-1, 1)
d = loss * x[i:i + bs]
d = d.sum(axis=0) / bs
d = lr * d
d.shape = (-1, 1)
w = w - d
y_ = np.dot(self.x, w)
loss_ = abs((y_ - y).sum())
print('\tLoss = ' + str(loss_))
print('拟合的结果为:', end=',')
print(sum(w.tolist(), []))
print()
if loss_ < self.eps:
print('The Gradient Descent algorithm has converged!!\n')
break
pass
def __call__(self, bs=1, lr=0.1, epoch=10):
if sys.version_info < (3, 4):
raise RuntimeError('At least Python 3.4 is required')
if not isinstance(bs, int) or not isinstance(epoch, int):
raise Exception(
"The type of BatchSize/Epoch should be an integer number")
self._gradient_descent(bs, lr, epoch)
pass
pass
if __name__ == "__main__":
if sys.version_info < (3, 4):
raise RuntimeError('At least Python 3.4 is required')
gd = GradientDescent([1.2, 1.4, 2.1, 4.5, 2.1])
# gd = GradientDescent([1.2, 1.4, 2.1])
print("要拟合的参数结果是: ")
print(gd.FuncArgs)
print("===================\n\n")
# gd.EPS = 0.0
gd.plotFunc()
gd(10, 0.01)
print("Finished!")

以上就是本文的全部内容,希望对大家的学习有所帮助。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python Socket网络编程实现C/S模式和P2P

    由于网络课需要实现Socket网络编程,所以简单实现了一下,C/S模式分别用TCP/IP协议与UDP协议实现,下面将分别讲解。

    砸漏
  • python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

    PyQt5中信号与槽可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个控件进行使用的,比如一个按钮,当我们使用按钮时,...

    砸漏
  • python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例

    最简单的多线程使用方法是利用QThread函数,展示QThread函数和信号简单结合的方法

    砸漏
  • jenkins python 接口封装

                    self.server = Jenkins(self.url)

    py3study
  • python爬虫教程:批量抓取 QQ 群信息

    本文讲解Python批量抓取 QQ 群信息,包括群名称、群号、群人数、群主、地域、分类、标签、群简介等内容,返回 XLS / CSV / JSON 结果文件。

    python学习教程
  • PyQt5信号、定时器及多线程

    信号是用于界面自动变化的一个工具,原理是信号绑定了一个函数,当信号被触发时函数即被调用

    嘘、小点声
  • 测试面试 | Python 算法与数据结构面试题系列二(附答案)

    ⬆️ 关注 @霍格沃兹测试学院 公众号,回复「面试」,领取 BAT 大厂测试面试真题专辑。

    霍格沃兹测试开发
  • 手把手教你使用Python打造一个爱奇艺热播好剧提前搜系统

    今年的疫情让我们很多人对于打工望而却步,没办法,钱可以再挣,但是生命只有一次,于是,宅在家的我们无事可做,只好看看电影来打发下我们无聊的时间。

    Python进阶者
  • 手把手教你用Python制作简易小说阅读器

    不知从什么时候开始。小说开始掀起了一股浪潮,它让我们平日里的生活不在枯燥乏味,很多我们做不到的事情在小说里都能轻易实现。

    Python进阶者
  • 用Python画出心目中的自己

    本项目主要来源于中科院和香港城市大学的一项研究DeepFaceDrawing,论文标题是《DeepFaceDrawing: DeepGeneration of ...

    博文视点Broadview

扫码关注云+社区

领取腾讯云代金券