Skorokhodov I, Burtsev M. Loss Landscape Sightseeing with Multi-Point Optimization.[J]. arXiv: Learning, 2019.

@article{skorokhodov2019loss,

title={Loss Landscape Sightseeing with Multi-Point Optimization.},

author={Skorokhodov, Ivan and Burtsev, Mikhail},

journal={arXiv: Learning},

year={2019}}

现在的任务是, 给出了第一幅图, 这是一只鸟,我们希望loss landscape 表现的同这只鸟一样. 换言之, 这幅图的一个像素点代表了一个相同规模的神经网络的在一网络参数下的损失(或者正确率). 黑色的部分表示这部分的网络我们希望他们能正确识别样本, 白色像素点希望他们错误识别样本. 第三幅图就是通过训练后的正确率的一个热点图.

所以这实际上一种正则化的过程.

主要内容

固定神经网络\(\mathcal{F}\)的模式,给定三组参数\(w_O, w_{right}, w_{up}\), 考虑如下线性组合

\[w_{\alpha, \beta} = w_O + \alpha w_{right} + \beta w_{up},
\]

这里我们视\(\alpha, \beta \in \{0, 1, 2, \ldots\}\), \(w_{\alpha, \beta}\)就是图片中第\((\alpha, \beta)\)个元素(看了作者代码,在实际操作中\(\alpha, \beta\)可以再同乘一个系数).

所以, 样本\(x\), 传入网络\(\mathcal{F}_{\alpha, \beta}\),

\[loss =
\left \{
\begin{array}{ll}
\mathcal{L}(\mathcal{F}_{\alpha, \beta}(x), y) &K(\alpha, \beta) = 1 \\
-\mathcal{L}(\mathcal{F}_{\alpha, \beta}(x), y) &K(\alpha, \beta) = -1 \\
\end{array} \right.
\]

其中\(K(\alpha, \beta)=1\)表示需要正确分类, 反之为不正确分类. 在代码中, 发现作者对\(K(\alpha, \beta)=-1\)的损失额外乘上了一个系数.

在作者的代码中, 并非是按序选择\(\mathcal{F}_{\alpha, \beta}\)的, 而是随机选择.

另外, 并非一定要限制在二维, 作者只是为了便于说明.

此外, 可以通过Schmidt正交法使得\(w_{right}, w_{up}\)正交, 这部分就不讲了(蛮简单的).

代码

作者的代码



"""
这部分相当于是作者代码中的layerops.py
个人认为代码的难点就在于此, 故只重写了这部分
的代码. 作者是完全重新定义Module模块, 我是在
Module的模块上进行修改.
""" import torch
import torch.nn as nn
import torch.nn.functional as F class Modulerebuild(nn.Module):
"""
对Module的部分方法进行重定义, 因为
一般的Module只接受Parameter, 这就要求
网络参数都是叶节点, 这与论文的思路不符
"""
def register_parameter(self, name: str, param):
if '_parameters' not in self.__dict__:
raise AttributeError(
"cannot assign parameter before Module.__init__() call") elif not isinstance(name, torch._six.string_classes):
raise TypeError("parameter name should be a string. "
"Got {}".format(torch.typename(name)))
elif '.' in name:
raise KeyError("parameter name can't contain \".\"")
elif name == '':
raise KeyError("parameter name can't be empty string \"\"")
elif hasattr(self, name) and name not in self._parameters:
raise KeyError("attribute '{}' already exists".format(name)) if param is None:
self._parameters[name] = None
elif not param.requires_grad:
raise ValueError("Invalid parameters, "
"the tensor should requires_grad == True")
else: self._parameters[name] = param def __setattr__(self, name, value):
def remove_from(*dicts):
for d in dicts:
if name in d:
del d[name] params = self.__dict__.get('_parameters')
if isinstance(value, torch.Tensor):
if params is None:
raise AttributeError(
"cannot assign parameters before Module.__init__() call")
remove_from(self.__dict__, self._buffers, self._modules)
self.register_parameter(name, value)
elif params is not None and name in params:
self.register_parameter(name, value)
else:
modules = self.__dict__.get('_modules')
if isinstance(value, Modulerebuild):
if modules is None:
raise AttributeError(
"cannot assign module before Module.__init__() call")
remove_from(self.__dict__, self._parameters, self._buffers)
modules[name] = value
elif modules is not None and name in modules:
if value is not None:
raise TypeError("cannot assign '{}' as child module '{}' "
"(torch.nn.Module or None expected)"
.format(torch.typename(value), name))
modules[name] = value
else:
buffers = self.__dict__.get('_buffers')
if buffers is not None and name in buffers:
if value is not None and not isinstance(value, torch.Tensor):
raise TypeError("cannot assign '{}' as buffer '{}' "
"(torch.Tensor or None expected)"
.format(torch.typename(value), name))
buffers[name] = value
else:
object.__setattr__(self, name, value) def parameters_(self):
"""
对parameters方法进行了重定义, 因为如果直接采用parameters() 结果
会返回空的生成器. 不直接在parameters上重定义的原因是, parameters的
参数设置与parameters_不同...
:return:
"""
for p in self._parameters.values():
yield p
for m in self._modules.values():
for p in m.parameters_():
yield p class Squentialrebuild(Modulerebuild): def __init__(self, *rebs):
super(Squentialrebuild, self).__init__()
self.rebs = rebs
for i, m in enumerate(self.rebs):
self.__setattr__(f'module_{i}', m) def forward(self, x):
for m in self.rebs:
x = m(x) return x def parameters_(self):
print(self._modules.values())
return super(Squentialrebuild, self).parameters() class Linearrebuild(Modulerebuild): def __init__(self, weight, bias=None):
super(Linearrebuild, self).__init__()
self.weight = weight
self.bias = bias def __call__(self, x):
return F.linear(x, self.weight, self.bias) class Conv2drebuild(Modulerebuild): def __init__(self, weight, bias=None, **kwargs):
super(Conv2drebuild, self).__init__()
self.weight = weight
self.bias = bias
self.kwargs = kwargs def forward(self, x):
return F.conv2d(x, self.weight, self.bias, **self.kwargs) class BatchNormrebuild(Modulerebuild): def __init__(self, weight, bias, **kwargs):
super(BatchNormrebuild, self).__init__()
self.weight = weight
self.bias = bias
self.kwargs = kwargs def forward(self, x):
dummy_mean = torch.zeros_like(self.bias)
dummy_var = torch.ones_like(self.weight)
return F.batch_norm(x, dummy_mean, dummy_var,
self.weight, self.bias,
training=True, **self.kwargs) class Net(Modulerebuild): def __init__(self, *rebs):
super(Net, self).__init__()
self.dense = Squentialrebuild(
*rebs
) def forward(self, x):
return self.dense(x) if __name__ == "__main__": parameters = []
rebs = []
weight = torch.rand(10, 2, requires_grad=True)
bias = torch.rand(10, requires_grad=True)
parameters += [weight, bias]
rebs.append(Linearrebuild(weight, bias))
weight = torch.rand(10, requires_grad=True)
bias = torch.rand(10, requires_grad=True)
parameters += [weight, bias]
rebs.append(BatchNormrebuild(weight, bias))
rebs.append(nn.ReLU())
weight = torch.rand(1, 10, requires_grad=True)
bias = torch.rand(1, requires_grad=True)
parameters += [weight, bias]
rebs.append(Linearrebuild(weight, bias + 1)) #注意我们这里传进去的bias+1不是叶节点 net = Net(*rebs)
x = torch.tensor([[1., 2.], [3., 4]])
y = torch.tensor([[1.], [2.]]) criterion = nn.MSELoss()
opti = torch.optim.SGD(parameters, lr=0.001) #虽然net.parameters_()可以获得参数, 但是
#里面的参数并非全是叶结点时, optim依旧无法
#进行更新
print(parameters[-1])
pred = net(x)
loss = criterion(pred, y)
opti.zero_grad()
loss.backward()
opti.step()
print(parameters[-1]) #但是可以发现bias的确发生了变化

Loss Landscape Sightseeing with Multi-Point Optimization的更多相关文章

  1. 损失函数(Loss Function) -1

    http://www.ics.uci.edu/~dramanan/teaching/ics273a_winter08/lectures/lecture14.pdf Loss Function 损失函数 ...

  2. (转) An overview of gradient descent optimization algorithms

    An overview of gradient descent optimization algorithms Table of contents: Gradient descent variants ...

  3. An overview of gradient descent optimization algorithms

    原文地址:An overview of gradient descent optimization algorithms An overview of gradient descent optimiz ...

  4. A Deep Neural Network’s Loss Surface Contains Every Low-dimensional Pattern

    目录 概 相关工作 主要内容 引理1 定理1 定理2 A Deep Neural Network's Loss Surface Contains Every Low-dimensional Patte ...

  5. zz先睹为快:神经网络顶会ICLR 2019论文热点分析

    先睹为快:神经网络顶会ICLR 2019论文热点分析 - lqfarmer的文章 - 知乎 https://zhuanlan.zhihu.com/p/53011934 作者:lqfarmer链接:ht ...

  6. How Do Vision Transformers Work?[2202.06709] - 论文研读系列(2) 个人笔记

    [论文简析]How Do Vision Transformers Work?[2202.06709] 论文题目:How Do Vision Transformers Work? 论文地址:http:/ ...

  7. caffe学习5——Model initialization and Model format

    参考文献 1 用Net::Init().做了两件事:一.绑架所有的layers和blobs,调用 layers’SetUp() 函数.验证全部网络的正确性等一系列琐碎的事.二.初始化时给出一些日志信息 ...

  8. Spring 2017 Assignments3

    一.作业要求 原版:http://cs231n.github.io/assignments2017/assignment3/ 翻译:http://www.mooc.ai/course/268/lear ...

  9. PaddlePaddle实现线性回归

    在本次实验中我们将使用PaddlePaddle来搭建一个简单的线性回归模型,并利用这一模型预测你的储蓄(在某地区)可以购买多大面积的房子.并且在学习模型搭建的过程中,了解到机器学习的若干重要概念,掌握 ...

随机推荐

  1. A Child's History of England.9

    But, first, as it was important to know how numerous those pestilent Danes were, and how they were f ...

  2. 【JAVA开发】浅析双亲委派机制

    双亲委派机制存在的意义 双亲委派只是一种说法,个人觉得叫单亲委派更合适,因为向上传递的父类只有一个,估计只是翻译过来的,形成的一种习惯,大家可以当做单亲委派 四种加载器都是用于类的加载,只是加载的对象 ...

  3. table表格数据无缝循环滚动

    分享一个好看的表格无缝滚动:(实战用起来很舒服) 直接copy代码到你的程序中: 1.HTML <div class="tablebox">              ...

  4. Hibernate的基本功能:对数据库的增删改查(创建对象实例)

    一.通过实例化的对象向数据库添加新记录 package com.yh.test; import org.hibernate.Session; import org.hibernate.SessionF ...

  5. ActiveMQ(三)——理解和掌握JMS(1)

    一.JMS基本概念 JMS是什么JMS Java Message Service,Java消息服务,是JavaEE中的一个技术. JMS规范JMS定义了Java中访问消息中间件的接囗,并没有给予实现, ...

  6. A New Discrete Particle Swarm Optimization Algorithm

    题目:一种新的离散粒子群优化算法 中文摘要 粒子群优化算法在许多优化问题上表现得非常好.粒子群优化算法的缺点之一是假设算法中的变量为连续变量.本文提出一个新的粒子群优化算法,能够优化离散变量.这个新算 ...

  7. CF688B Lovely Palindromes 题解

    Content 输入一个数 \(n\),输出第 \(n\) 个偶数位回文数. 数据范围:\(1\leqslant n\leqslant 10^{10^5}\). Solution 一看这吓人的数据范围 ...

  8. CF31B Sysadmin Bob 题解

    Content 给定一个字符串 \(s\),请将其分解为诸如 \(\texttt{xx@xx}\) 的子串,并将分解后的所有子串输出,或者说不存在这样的方案. 数据范围:\(1\leqslant|s| ...

  9. CF675A Infinite Sequence 题解

    Content 给定三个整数 \(a,b,c\),问你 \(b\) 是否在以 \(a\) 为首项,公差为 \(c\) 的等差数列中. 数据范围:\(-10^9\leqslant a,b,c\leqsl ...

  10. urllib结合 concurrent.futures 多线程下载文件。

    示例: #!/usr/bin/env python3 # -*- coding:utf-8 -*- # @Time: 2020/12/16 10:42 # @Author:zhangmingda # ...