线性回归 ,softmax,多层感知机

一 线性回归模型最要是描述输入输出的线性关系,

例如:房屋价格与房子面积和房子年龄的关系

为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。线性回归假设输出与各个输入之间是线性关系:

price=warea⋅area+wage⋅age+b

二 优化函数 - 随机梯度下降

当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。

在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient descent)在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch)B,然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。

\left ( w,b \right )\leftarrow(w,b)-\frac{\jmath }{B}\sum_{i\epsilon B}\partial \left ( w,b \right )l^{\left ( i \right )}\left ( w,b \right )

学习率: j代表在每次优化中,能够学习的步长的大小
批量大小: B是小批量计算中的批量大小batch size

总结一下,优化函数的有以下两个步骤:

  • (i)初始化模型参数,一般来说使用随机初始化;

  • (ii)我们在数据上迭代多次,通过在负梯度方向移动参数来更新每个参数。

 

建模:

三 初始化模型参数

1,自定义方法

2,调用torch中

w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32)

b = torch.zeros(1, dtype=torch.float32)

w.requires_grad_(requires_grad=True)

b.requires_grad_(requires_grad=True)

的init

from torch import init

from torch import nn

net =nn.Sequential(nn.Linear(num_inputs,num_outputs)

init.normal_(net[0].weight,mean=0,std=0.1) 

init.canstant_(net[0].bais,val=0.3)

或者:

init.normal_(net.pramasters(),mean=0,std=0.1)

四 pytorch 模型叠加构建

# 初始化多层模型网络
nn.Sequential是一个存放模型的序列列表
里面的模型访问与访问list中的元素相同,可通过下表访问
# 方法一

net = nn.Sequential(
    nn.Linear(num_inputs, num_outputs)
    # 在这里写其他层网络
    )


nn.Sequential是一个存放模型的序列列表
里面的模型访问与访问list中的元素相同,可通过下表访问

print(net[0])
>>> (0) nn.Linear(num_inputs,num_outputs)


# 方法二

net = nn.Sequential()
#add_module(),添加模型,
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......(接着添加其他层)

# 方法三
将模型放在一个有序的字典里,OrderedDict会根据放入元素的先后顺序进行排序;
python中普通的字典中,元素顺序是不作要求

dict1={'a':1,'b':2,'c':3}
dict2={'c':3,'b':2,'a':1}
print(dict1==dict2)
>>> True

dict3=OrderedDict({'a':1,'b':2,'c':3})
dict4=OrderedDict({'c':3,'b':2,'a':1})
print(dict3==dict4)
>>> False

from collections import OrderedDict
net = nn.Sequential(OrderedDict([
          ('linear', nn.Linear(num_inputs, 1))
          # ......
        ]))


访问模型可通过net.linear
 

softmax的基本概念
分类问题

        分类问题需要得到离散的预测输出,一个简单的办法是将输出值Oi,当作预测类别是i的置信度,并将值最大的输出所对应的类作为预测输出,即输出 argmax(Oi)。例如,如果O1,O2,O3分别为0.1,10, 0.1,由于O2最大,那么预测类别为2

输出问题
直接使用输出层的输出有两个问题:

一方面,由于输出层的输出值的范围不确定,我们难以直观上判断这些值的意义。例如,刚才举的例子中的输出值10表示“很置信”图像类别为2,因为该输出值是其他两类的输出值的100倍。但如果O1=1000,O2=10,O3=1000 ,那么输出值10却又表示图像类别为2的概率很低。
另一方面,由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量;
                   

注意:在实际应用中使用softmax需要注意数值溢出问题,当O1,O2,O3数组很大时

如 softmax(100,101,102),  运算结果会出问题

解决办法: 将O1,O2,O3将去他们的最大值,在算softmax

a=max(O1,O2,O3)

softmax(O1,O2,O3)==softmax(O1-a,O2-a,O3-a)

softmax(100,101,102)==softmax(-2,-1,0)

 

#获取MNIST数据集

方法一:优点自动下载代码简单,缺点下载慢

mnist_train = torchvision.datasets.FashionMNIST(root='/home/kesci/input/FashionMNIST2065', train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='/home/kesci/input/FashionMNIST2065', train=False, download=True, transform=transforms.ToTensor())

class torchvision.datasets.FashionMNIST(root, train=True, transform=None, target_transform=None, download=False)

root(string)– 数据集的根目录,其中存放processed/training.pt和processed/test.pt文件。

train(bool, 可选)– 如果设置为True,从training.pt创建数据集,否则从test.pt创建。

download(bool, 可选)– 如果设置为True,从互联网下载数据并放到root文件夹下。如果root目录下已经存在数据,不会再次下载。

transform(可被调用 , 可选)– 一种函数或变换,输入PIL图片,返回变换之后的数据。如:transforms.RandomCrop。

target_transform(可被调用 , 可选)– 一种函数或变换,输入目标,进行变换。

方法二:优点速度极快,缺点步骤稍微繁琐

步骤一   先到网站下载MNIST的.gz文件    http://yann.lecun.com/exdb/mnist/

一共四个文件,最大的不超过10MB

步骤二: 将这四个文件解压

步骤三:运行下面代码即可

以下代码只需更改somePath为你下载的文件的路径

import numpy as np
import struct
from PIL import Image
import os
 
#处理train数据
somePath='C:/Users/zzh/Desktop/MSINT/'
data_file = somePath +'train-images.idx3-ubyte' 
# It's 47040016B, but we should set to 47040000B
data_file_size = 47040016
data_file_size = str(data_file_size - 16) + 'B'
 
data_buf = open(data_file, 'rb').read()
 
magic, numImages, numRows, numColumns = struct.unpack_from(
    '>IIII', data_buf, 0)
datas = struct.unpack_from(
    '>' + data_file_size, data_buf, struct.calcsize('>IIII'))
datas = np.array(datas).astype(np.uint8).reshape(
    numImages, 1, numRows, numColumns)
 
label_file = somePath+'train-labels.idx1-ubyte' 
 
# It's 60008B, but we should set to 60000B
label_file_size = 60008
label_file_size = str(label_file_size - 8) + 'B'
 
label_buf = open(label_file, 'rb').read()
 
magic, numLabels = struct.unpack_from('>II', label_buf, 0)
labels = struct.unpack_from(
    '>' + label_file_size, label_buf, struct.calcsize('>II'))
labels = np.array(labels).astype(np.int64)
 
datas_root = somePath + 'mnist_train' 
if not os.path.exists(datas_root):
    os.mkdir(datas_root)
 
for i in range(10):
    file_name = datas_root + os.sep + str(i)
    if not os.path.exists(file_name):
        os.mkdir(file_name)
 
for ii in range(numLabels):
    img = Image.fromarray(datas[ii, 0, 0:28, 0:28])
    label = labels[ii]
    file_name = datas_root + os.sep + str(label) + os.sep + \
        'mnist_train_' + str(ii) + '.png'
    img.save(file_name)
 
 
 
#处理test数据
somePath='C:/Users/zzh/Desktop/MSINT/'
data_file = somePath+'t10k-images.idx3-ubyte' 
 
# It's 7840016B, but we should set to 7840000B
data_file_size = 7840016
data_file_size = str(data_file_size - 16) + 'B'
 
data_buf = open(data_file, 'rb').read()
 
magic, numImages, numRows, numColumns = struct.unpack_from(
    '>IIII', data_buf, 0)
datas = struct.unpack_from(
    '>' + data_file_size, data_buf, struct.calcsize('>IIII'))
datas = np.array(datas).astype(np.uint8).reshape(
    numImages, 1, numRows, numColumns)
 
label_file = somePath+'t10k-labels.idx1-ubyte'
 
# It's 10008B, but we should set to 10000B
label_file_size = 10008
label_file_size = str(label_file_size - 8) + 'B'
 
label_buf = open(label_file, 'rb').read()
 
magic, numLabels = struct.unpack_from('>II', label_buf, 0)
labels = struct.unpack_from(
    '>' + label_file_size, label_buf, struct.calcsize('>II'))
labels = np.array(labels).astype(np.int64)
 
datas_root = somePath+'mnist_test' 
 
if not os.path.exists(datas_root):
    os.mkdir(datas_root)
 
for i in range(10):
    file_name = datas_root + os.sep + str(i)
    if not os.path.exists(file_name):
        os.mkdir(file_name)
 
for ii in range(numLabels):
    img = Image.fromarray(datas[ii, 0, 0:28, 0:28])
    label = labels[ii]
    file_name = datas_root + os.sep + str(label) + os.sep + \
        'mnist_test_' + str(ii) + '.png'
    img.save(file_name)

#多维tensor求和

X = torch.tensor([[1,2,3],[4,5,6]])

print(X.sum(dim=0, keepdim=True))  # dim为0,按照相同的列求和,并在结果中保留列特征
print(X.sum(dim=1, keepdim=True))  # dim为1,按照相同的行求和,并在结果中保留行特征
print(X.sum(dim=0, keepdim=False)) # dim为0,按照相同的列求和,不在结果中保留列特征
print(X.sum(dim=1, keepdim=False)) # dim为1,按照相同的行求和,不在结果中保留行特征

>>>   tensor([[5,7,9]])  shape   (1X3)

>>>   tensor([6],[15])   shape   (2X1)

>>>   tensor([5,7,9])    shape    (3)

>>>   tensor([6,15])     shape    (2)

 

多层感知机的基本知识

深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。

隐藏层

下图展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。

Image Name

表达公式

           具体来说,给定一个小批量样本X∈R^{n\times d},其批量大小为n,输入个数为d。假设多层感知机只有一个隐藏层,其中隐藏单元个数为h。记隐藏层的输出(也称为隐藏层变量或隐藏变量)为H,有H∈R^{n\times h}。因为隐藏层和输出层均是全连接层,可以设隐藏层的权重参数和偏差参数分别为Wh∈R^{d\times h}和 bh∈R^{1\times h},输出层的权重和偏差参数分别为Wo∈R^{h\times d}和bo∈R^{1\times q}

我们先来看一种含单隐藏层的多层感知机的设计。其输出O∈R^{n\times q}的计算为

                                              \begin{aligned} \boldsymbol{H} &= \boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h,\\ \boldsymbol{O} &= \boldsymbol{H} \boldsymbol{W}_o + \boldsymbol{b}_o, \end{aligned}

也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到

\boldsymbol{O} = (\boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h)\boldsymbol{W}_o + \boldsymbol{b}_o = \boldsymbol{X} \boldsymbol{W}_h\boldsymbol{W}_o + \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o.

从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络:其中输出层权重参数为\boldsymbol{W}_h\boldsymbol{W}_o,偏差参数为\boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o。不难发现,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。

 

二    tensor张量求导

backward() 函数求导注意事项

backward() 函数是反向求导,使用链式求导法则求导,适用于标量求导,如果对于非标量y求导,函数需要额外指定grad_tensor,且grad_tensor的shape 必需和y一致,对于非标量y求导,也可先将y求和变成标量之后再求导(y.sum().backgrad())

可参考https://blog.csdn.net/shiheyingzhe/article/details/83054238 理解

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值