PYTORCH学习(2):梯度下降、随机梯度下降、mini batch、反向传播

PYTORCH学习(2):梯度下降、随机梯度下降、mini batch

  • 1、学习点
    • 1.1 非凸函数
    • 1.2 鞍点问题
    • 1.3 前向传播和反向传播
  • 2、python实现
    • 2.1 梯度\随机梯度下降
    • 2.2 mini batch python 实现
    • 2.3 反向传播(pytorch实现)

1、学习点

1.1 非凸函数

凸函数性质:函数上任取两点连成线段,取其中点,中点的纵坐标值大于该点映射在函数上的值。
凸函数优点:局部最优=全局最优
但现实中绝大多数的问题函数都是非凸(凹)函数,局部最优值不等于全局最优值,那么我们不想只找到局部最优解,怎么去解决这个问题从而找到全局最优解呢?

1.2 鞍点问题

在高维空间中,可能存在一个点在一个维度上是极大值,在另一个维度上却是极小值,这种点会使神经网络的参数更新变得艰难,因为当遇到这种点的时候,总体的梯度值为0,参数无法更新。为了解决这个问题,梯度下降法进化为了随机梯度下降法。

1.3 前向传播和反向传播

目的:前向传播为了求取损失函数值反向传播为了更新参数,使得参数往损失函数值小的方向走。
流程:前向传播——》反向传播——》前向传播。。。。(迭代N次)

2、python实现

2.1 梯度\随机梯度下降

#输入数据
input_x = [1.0,2.0,3.0,5.0,9.0]
input_y = [2.8,6.5,8.9,14.9,25.7]

#初始化权重和定义学习率
w = 1.0
learn_rate = 0.01

#定义线性模型
def linear(x):
    y = w * x
    return y

#定义损失函数(MSE)
# 梯度下降用的
# def cost(input_x,input_y):
#     loss = 0
#     for x,y in zip(input_x,input_y):
#         compute_y = linear(x)
#         loss += (compute_y-y)**2
#     return loss/len(input_x)
#随机梯度下降用的
def loss(x,y):
    compute_y = linear(x)
    return (compute_y-y)**2

#定义梯度计算函数
# 梯度下降用的
# def gradient(input_x,input_y):
#     grad = 0
#     for x, y in zip(input_x, input_y):
#         grad += 2 * x * (linear(x) - y)
#     return grad
# 随机梯度下降用的
def gradient(x,y):
    grad = 2 * x * (linear(x) - y)
    return grad

if __name__ == '__main__':
    #梯度下降用的
    # for epoch in range(100):
    #     loss_val = loss(input_x,input_y)
    #     grad = gradient(input_x,input_y)
    #     w -= learn_rate * grad
    #     print("epoch:",epoch,"w=",w,"loss=",loss_val)
    # 随机梯度下降用的
    for epoch in range(100):
        for x, y in zip(input_x, input_y):
            loss_val = loss(x, y)
            grad = gradient(x, y)
            w -= learn_rate * grad
        print("epoch:",epoch,"w=",w,"loss=",loss_val)

梯度下降法的更新用的是总样本的梯度(可以并行计算,速度更快,但是存在鞍点问题);随机梯度下降法的更新用的是每一个样本的梯度(不可以并行计算,速度更慢,但是解决了鞍点问题)。
采用折中:使用batch,不是使用总样本,也不是一个一个来,而是将总样本拆成好几份,一份一份地训练

2.2 mini batch python 实现

import math

#输入数据
input_x = [1.0, 2.0, 3.0, 5.0, 5.6, 9.0]
input_y = [2.8, 6.5, 8.9, 14.9, 16, 25.7]

#初始化权重和定义学习率
w = 1.0
learn_rate = 0.01
batch = 3

#定义线性模型
def linear(x):
    y = w * x
    return y

#定义损失函数(MSE)
# 梯度下降用的/batch
def cost(input_x,input_y):
    loss = 0
    for x,y in zip(input_x,input_y):
        compute_y = linear(x)
        loss += (compute_y-y)**2
    return loss/len(input_x)

#定义梯度计算函数
# 梯度下降用的/batch
def gradient(input_x,input_y):
    grad = 0
    for x,y in zip(input_x, input_y):
        grad += 2 * x * (linear(x) - y)
    return grad

if __name__ == '__main__':
    #batch
    count = math.ceil(len(input_x) / batch)
    count_now = 1
    num = 0
    flag = 0
    best_w = 0
    min_loss = 99999999
    for epoch in range(100):
        flag = 1
        while flag == 1:
            ix = []
            iy = []
            if count_now < count or count_now == 1:
                ix = (input_x[(count_now-1) * batch : count_now * batch])
                iy = (input_y[(count_now-1) * batch : count_now * batch])
                count_now += 1
            elif len(input_x) % batch != 0:
                ix = (input_x[(count_now-1) * batch : ])
                iy = (input_y[(count_now-1) * batch : ])
                count_now = 1
                flag = 0
            else:
                flag = 0
                count_now = 1

            if len(ix) != 0:
                loss_val = cost(ix, iy)
                grad = gradient(ix, iy)
                w -= learn_rate * grad
                if loss_val < min_loss:
                    best_w = w
                    min_loss = loss_val
                    print("epoch:",epoch,"w=",w,"loss=",loss_val)

2.3 反向传播(pytorch实现)

映射函数式为 f ( x ) = w 1 ∗ x 2 + w 2 ∗ x + b f(x)=w_1*x^2+w_2*x+b f(x)=w1x2+w2x+b

import torch

#输入数据
input_x = [1.0, 2.0, 3.0, 5.0, 5.6, 9.0]
input_y = [2.8, 6.5, 8.9, 14.9, 16, 25.7]
# input_x = [1.0,2.0,3.0]
# input_y = [2.0,4.0,6.0]

#初始化权重和定义学习率
w1 = torch.Tensor([1.0]) #参数创建为张量类型
w1.requires_grad = True #张量Tensor包括data和grad,前者是存放参数值,后者是存放反向传播计算得到的梯度值

w2 = torch.Tensor([1.0])
w2.requires_grad = True

b = torch.Tensor([1.0])
b.requires_grad = True

learn_rate = 0.01 #学习率

#定义映射函数
def forward(x):
    y = w1 * x ** 2 + w2 * x + b
    return y

#定义损失函数(MSE)
def loss(x,y):
    compute_y = forward(x)
    return (compute_y - y) ** 2

if __name__ == '__main__':
    # 随机梯度下降用的
    for epoch in range(100):
        for x, y in zip(input_x, input_y):
            loss_val = loss(x, y)
            loss_val.backward()
            print('\tgrad:',x,y,w1.grad.item(),w2.grad.item(),b.grad.item())
            w1.data = w1.data - learn_rate * w1.grad.data #梯度更新
            w2.data = w2.data - learn_rate * w2.grad.data
            b.data = b.data - learn_rate * b.grad.data

            # print(type(w1.grad.data)) w1.grad.data为张量
            # print(type(w1.grad.item())) w1.grad.item()为常数

            w1.grad.data.zero_() #清空存放的梯度值,准备下一次计算的开始
            w2.grad.data.zero_()
            b.grad.data.zero_()

        print("epoch:",epoch,"loss:",loss_val.item())

你可能感兴趣的:(python,1024程序员节,pytorch,人工智能,深度学习)