线性单元与随机梯度下降算法

代码所用数据:代码中x代表Ones(x0)和Population(x1),yi代表Profits(利润)
在这里插入图片描述

代码实现

# SGD(随机梯度下降法)
import numpy as np

np.seterr(divide='ignore', invalid='ignore')


class SGD:
    def __init__(self, learning_rate, w):
        self.lr = learning_rate  # 学习率
        self.w = np.array(w)  # 权重

    @staticmethod
    def training_data(train_data):  # train_data:包括特征值和真实值
        cols = train_data.shape[1]
        xt, yi = train_data[:, 0:cols - 1], train_data[:, cols - 1:cols]
        return [xt, yi, train_data]

    def linear_func(self, x):
        y_pre = []
        for i in range(len(x)):
            y = np.dot(self.w, x[i])  # 线性单元
            y_pre.append(y)
        print(f'这是进行随机梯度下降前的线性模型得到的预测值: {y_pre}')

    def loss_func(self, x, yi):
        diff_sqrs = []  # 存储预测值与真实值差的平方
        for i in range(len(x)):
            diff_sqr = (np.dot(self.w, x[i]) - yi[i]) ** 2
            diff_sqrs.append(diff_sqr)
        Loss = (1 / (2 * len(yi))) * np.sum(diff_sqrs)
        Loss_aver = Loss / len(yi)
        print(f'这是进行随机梯度下降前的线性模型的平均损失值: {Loss_aver}')

    # @staticmethod
    # def getRandomIndex(n, x):
    #     index = np.random.choice(np.arange(n), size=x, replace=False)
    #     return index

    def sgd(self, train_data, epoch):
        count = 1
        while count < epoch:
            np.random.shuffle(train_data)  # 将train_data乱序
            tda = SGD.training_data(train_data)
            x, yi = tda[0], tda[1]
            for i in range(len(x)):
                self.lr = self.lr / count  # 更新学习率
                self.w -= self.lr * (np.dot(self.w, x[i]) - yi[i]) * x[i]
                for j in range(len(x[0])):
                    if 0 <= ((np.dot(self.w, x[i]) - yi[i]) * x[i])[j] <= 0.1:
                        break
            count += 1
        return self.w

    @staticmethod
    def test(w, x, yi):
        diff_sqrs, y_test = [], []
        for i in range(len(x)):
            y = np.dot(w, x[i])
            diff_sqr = (y - yi[i]) ** 2
            y_test.append(y)
            diff_sqrs.append(diff_sqr)
        Loss = (1 / (2 * len(yi))) * np.sum(diff_sqrs)
        Loss_aver = Loss / len(yi)
        print(f'这是进行随机梯度下降后的线性模型得到的预测值: {y_test},\n'
              f'这是进行随机梯度下降后的线性模型的平均损失值: {Loss_aver},\n'
              f'这是进行随机梯度下降后的线性模型的权重: {w}')


if __name__ == '__main__':
    SGD = SGD(0.03, np.array([1, 0.5]))
    td = SGD.training_data(np.array([[1, 6.1101, 17.5920], [1, 5.5277, 9.1302], [1, 8.5186, 13.6620],
                                     [1, 7.0032, 11.8540], [1, 5.8598, 6.8233]]))
    SGD.linear_func(td[0])
    SGD.loss_func(td[0], td[1])
    W = SGD.sgd(td[2], 2000000)
    SGD.test(W, td[0], td[1])

运行结果

这是进行随机梯度下降前的线性模型得到的预测值: [4.05505, 3.76385, 5.2593, 4.5016, 3.9299]
这是进行随机梯度下降前的线性模型的平均损失值: 6.9016328847
这是进行随机梯度下降后的线性模型得到的预测值: [9.908140274362793, 14.57381770427882, 10.426202220424216, 12.209857833572762, 10.816659628130253],
这是进行随机梯度下降后的线性模型的平均损失值: 1.208987579173057,
这是进行随机梯度下降后的线性模型的权重: [1.2851622 1.55995768]

总结

我虽然在大二时在大三学长的影响下就接触了机器学习和深度学习,但实际的学习和编程到了大三才真正开始。在任老师的亲身传授下,我相继完成了感知器和随机梯度下降算法的学习和编程。(感兴趣的小伙伴可以进入我的主页浏览感知机(代码实现)线性单元与随机梯度下降算法。本人编程能力有限,代码可能有逻辑上的错误或者不够简洁,烦请各路大神给小生指点一二,在评论区留个言,本人将不胜感激)感知器的编程相对比较简单,但随机梯度下降算法的编程让我犯了难。首先是对于随机的理解上,一开始在对权重w进行梯度下降时,梯度我采用了求和的形式。我后来在查阅了一些资料并结合老师的讲解才逐渐的明白了“随机”的含义。依照我个人的理解,整个的随机梯度下降法的实现流程是这样的:
(1)首先初始化一个训练次数epoch用于循环以及缩小学习率。
(2)将训练数据(包含输入和输出)打乱顺序放在循环之中,每一次循环,训练数据的顺序都会被重新打乱。
(3)将打乱的训练数据分成输入和输出。
(4)进行梯度下降,每一次更新权重w时只使用一个训练数据的梯度,而不是采用梯度和的形式
代码如下

        count = 1
        while count < epoch:
            np.random.shuffle(train_data)  # 将train_data乱序
            tda = SGD.training_data(train_data)
            x, yi = tda[0], tda[1]
            for i in range(len(x)):
                self.lr = self.lr / count  # 更新学习率
                self.w -= self.lr * (np.dot(self.w, x[i]) - yi[i]) * x[i]
                for j in range(len(x[0])):
                    if 0 <= ((np.dot(self.w, x[i]) - yi[i]) * x[i])[j] <= 0.1:
                        break
            count += 1

参考链接

随机梯度下降算法的Python实现
随机梯度下降算法的步长选择

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值