예제 #1
0
# 下面是从零开始的完整实现
features, labels = data_process.get_data_ch7()


# 初始化参数
def init_rmsprop_states():
    s_w = torch.zeros((features.shape[1], 1), dtype=torch.float32)
    s_b = torch.zeros(1, dtype=torch.float32)
    return (s_w, s_b)


def rmsprop(params, states, hyperparams):
    # 关键在于超参数gamma的引入
    gamma, eps = hyperparams['gamma'], 1e-6
    for p, s in zip(params, states):
        # 新的s的生成带有了gamma的加权
        s.data = gamma * s.data + (1 - gamma) * (p.grad.data)**2
        p.data -= hyperparams['lr'] * p.grad.data / torch.sqrt(s + eps)


# 新的训练可以看到即使在训练的末尾线条也可能出现一些波动了
train.train_ch7(rmsprop, init_rmsprop_states(), {'lr': 0.01, 'gamma': 0.9},
                features, labels)
print('————————————————————————————')

# 简洁实现可以直接调用库中的RMSprop优化器,但是这里的gamma变为了alpha超参数
train.train_pytorch_ch7(torch.optim.RMSprop, {
                        'lr': 0.01, 'alpha': 0.9}, features, labels)
print('————————————————————————————')
예제 #2
0
def init_adadelta_states():
    s_w, s_b = torch.zeros(
        (features.shape[1], 1),
        dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
    # 需要额外初始化参数delta,用来调整临时梯度的值
    delta_w, delta_b = torch.zeros(
        (features.shape[1], 1),
        dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
    return ((s_w, delta_w), (s_b, delta_b))


def adadelta(params, states, hyperparams):
    # 这里的rho相当于AdaGrad的gamma
    rho, eps = hyperparams['rho'], 1e-5
    for p, (s, delta) in zip(params, states):
        s[:] = rho * s + (1 - rho) * (p.grad.data**2)
        # 对临时梯度使用了更复杂的更新方法,关键是使用了(delta + eps)来代替之前所需的
        # 学习率
        g = p.grad.data * torch.sqrt((delta + eps) / (s + eps))
        p.data -= g
        # delta在使用后也得进行更新,更新方法类似于对中间值s的更新
        delta[:] = rho * delta + (1 - rho) * g * g


train.train_ch7(adadelta, init_adadelta_states(), {'rho': 0.9}, features,
                labels)
print('————————————————————————————')

# 简洁实现依然是使用库已经写好的Adadelta,库的版本一开始的时候loss就比较低了
train.train_pytorch_ch7(torch.optim.Adadelta, {'rho': 0.9}, features, labels)
예제 #3
0
def train_sgd(lr, batch_size, num_epochs=2):
    train.train_ch7(sgd, None, {'lr': lr}, features, labels, batch_size,
                    num_epochs)
예제 #4
0
# 这里开始从零开始实现AdaGrad优化器,重点是维护控制学习率的变量
# 这里使用大一些的数据来测试
features, labels = data_process.get_data_ch7()


# 初始化参数
def init_adagrad_states():
    s_w = torch.zeros((features.shape[1], 1), dtype=torch.float32)
    s_b = torch.zeros(1, dtype=torch.float32)
    return (s_w, s_b)


def adagrad(params, states, hyperparams):
    eps = 1e-6
    # 对每个参数对应的学习率按公式设置然后应用到参数上
    for p, s in zip(params, states):
        # 按照梯度大小提高s的值,也就是减小学习率,使用了平方使得s只增不减
        s.data += (p.grad.data**2)
        # 用类似学习率的用法来使用s,s作为学习率的权重
        p.data -= hyperparams['lr'] * p.grad.data / torch.sqrt(s + eps)


# 对比上节的动量法可以看到这次下降很快而且收敛后也很稳定
train.train_ch7(adagrad, init_adagrad_states(), {'lr': 0.1}, features, labels)
print('————————————————————————————')

# 简洁实现只要使用库函数即可
train.train_pytorch_ch7(torch.optim.Adagrad, {'lr': 0.1}, features, labels)
print('————————————————————————————')
예제 #5
0
    beta1, beta2, eps = 0.9, 0.999, 1e-6
    for p, (v, s) in zip(params, states):
        # 更新v和s
        v[:] = beta1 * v + (1 - beta1) * p.grad.data
        s[:] = beta2 * s + (1 - beta2) * p.grad.data**2
        # 使用记录下来的超参数时间步t来进行偏差修正,这是因为由于加权平均和极限的原因,
        # 只截取一部分值进行估算既准确又不准确,一开始初始化的辅助参数0可能会导致很大
        # 的偏差,尽管在计算链长的时候前面的值会被近似忽略,但是在数据刚开始计算的时候
        # 影响可能很大,而且难以用多次加权来处理
        # 对时间步的偏差修正大幅减少了前期数据对总体数据的影响,因而能得到更准确的移动
        # 加权平均的结果
        v_bias_corr = v / (1 - beta1**hyperparams['t'])
        s_bias_corr = s / (1 - beta2**hyperparams['t'])
        # 应用到参数上
        p.data -= hyperparams['lr'] * v_bias_corr / \
            (torch.sqrt(s_bias_corr) + eps)
    # 更新超参数时间步
    hyperparams['t'] += 1


# 训练测试,现在的优化算法由于RMSprop部分使得下降比较稳定,又由于动量法部分下降很快
train.train_ch7(adam, init_adam_states(), {
    'lr': 0.01,
    't': 1
}, features, labels)
print('————————————————————————————')

# 简洁实现
train.train_pytorch_ch7(torch.optim.Adam, {'lr': 0.01}, features, labels)
print('————————————————————————————')