1.神经网络

(1)网络结构的定义:

import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 1个输入通道,6个输出通道,卷积尺度为5*5
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # 一个映射变换:y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
        
    def forward(self,x):
        # 使用最大池化,滑动窗口尺度(2,2)
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # 如果大小为正方形,则只需要指定一个数字
        x = F.max_pool2d(F.relu(self.conv2(x)),2)
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    def num_flat_features(self,x):
        size = x.size()[1:]  # 除批尺寸维度以外的其他所有维度
        num_features = 1
        for s in size:
            num_features *= s
        return num_features
net = Net()
print(net)
  • self.fc1=nn.Linear(input_size,output_size)
    神经网络的线性层常作为全连接层,是一个映射变换:y = Wx + b,应用于矩阵中则表现为类似于矩阵乘法。
input=torch.Tensor(256,256)   
 fc=nn.Linear(256,10)
 output=fc(input)  #[256,256]*[256,10]=[256,10]
  • 输出如下
Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

(2)训练网络

#设置迭代次数
epoch_num=10000

# 创建一个优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)

#创建网络模型
model=net()

# 训练循环中
for epoch in epoch_num :
    input = torch.randn(1, 1, 32, 32)
	optimizer.zero_grad() #梯度置零
	output = net(input)
	
	target = torch.randn(10) # 举例虚设的目标
    target = target.view(1, -1) # 转换为与输出相同的尺度,其中-1表示没有约束
	
	#损失函数
	criterion = nn.MSELoss()
	loss = criterion(output, target)
	loss.backward()
	optimizer.step() #更新权重

**(3)采样取batch **

# BatchSampler是个批量采样器,一次返回 batch_size个索引,RandomSampler随机采样
from torch.utils.data import BatchSampler, SequentialSampler, RandomSampler
 batch_idxs= list(BatchSampler(RandomSampler(
                range(data_size1)), batch_size=self.batch_size, drop_last=True))

batch_idxs为二维数据batch_idxs[data_size/batch_size][batch_size]

(4)关于input的一些常见的转换

  • 传入model的batch应该为相同的tensor
for i in range(len(batch_idxs)):
 				#取出一个batch并传入batch_x1,x1中包括所有的input数据
                batch_idx=batch_idxs[i]
                batch_x1=[]
                for i in range(len(batch_idx)):
                    a=x1[batch_idx1[i]]
                    batch_x1.append(a)
                    
                self.optimizer.zero_grad()  # 先清零
                
                #将batch_x1处理为longTensor后传入网络
                batch_x1= torch.cat(batch_x1, dim=0)#tensor 1456*436*364     3*256,256,3
                batch_x1 = batch_x1.view(len(batch_idx1),input_shape1[0],input_shape1[1],-1)#3,256,256,3 dpype=toech.float32  #3,256,256,3
                batch_x1 = batch_x1.permute(0, 3, 1, 2)#3,3,256,256 
                batch_x1=batch_x1.type(torch.double)#数据类型由float32转为double(即float64)

1. torch.cat()
将两个tensor拼接在一起

  • dims=0

C=torch.cat((A,B),0)就表示按维数0(行)拼接A和B,也就是竖着拼接,A上B下。此时需要注意:列数必须一致,即维数1数值要相同,这里都是3列,方能列对齐。拼接后的C的第0维是两个维数0数值和,即2+4=6.

  • dims=1

C=torch.cat((A,B),1)就表示按维数1(列)拼接A和B,也就是横着拼接,A左B右。此时需要注意:行数必须一致,即维数0数值要相同,这里都是2行,方能行对齐。拼接后的C的第1维是两个维数1数值和,即3+4=7.

  • 限制

使用torch.cat((A,B),dim)时,除拼接维数dim数值可不同外其余维数数值需相同,方能对齐。

2. torch.view()
view函数旨在reshape张量形状,返回一个有相同数据但是不同形状的新的向量。
使用view容易对数据结构造成破坏,需要想清楚

  • 将所有的数据都展开为一列,然后根据所设置的shape组织。

3. torch.permute(dims)
permute是维度换位,是更灵活的transpose,可以灵活的对原数据的维度进行调换,而数据本身不变。

  • dim (int) - 指定换位顺序

tensor为四维时,则dim应该为0,1,2,3,分别对应tensor中相应的维度,若第一维不变,需要将第二维与第四维转换,第三维与二维转换,第四维度与第三维转换则: x1 = x1.permute(0, 3, 1, 2)

4. torch.typetorch(torch.double)
更改tensor的数据类型

(5)卷积层

import torch
import torch.nn as nn
import numpy as np
from torch.autograd import Variable

x = torch.Tensor([1, 10, 100, 1000, 10000, 100000]).view(1, 2, -1, 1, 1)
# view()函数用来reshape,-1参数意为自动设置,此处计算得6
# Conv2d的规定输入数据格式为(batch, channel, Height, Width)
# Conv3d的规定输入数据格式为(batch, channel, Depth, Height, Width)
x = Variable(x)

conv = nn.Conv3d(in_channels=2,
                 out_channels=6,
                 kernel_size=(2, 1, 1),
                 stride=1,
                 padding=0,
                 dilation=1,
                 groups=1,
                 bias=False)

# 参数group的作用为:将输入数据按通道顺序分组, 每组有in_channel/group个通道.(例:group为2时,输入数据前一半通道为一组)
# 	同时, 每组对应的kernel个数, 从原来的out_channel变为outchannel/group.
# 此处的kernel为三维及以上结构,而filter特指二维层状的过滤器。
# 	原来的情况中, 每个生成的特征图都有所有通道的贡献.
# 	而现在, 特征图仅由其所在group对应的通道卷积构成.
# 简而言之, group参数的目的就是将原本的大卷积分成多个并联(side by side)的小卷积
# 另: 在in_channel不变的情况下, 当group>1时, kernel总数不变, 而filter总数缩小group倍.
# 而在filter、kernel总数不变的情况下, group增大, 需要的in_channel按同样比例增大.

# 参数dilation的作用为: 控制卷积核元素的间隔大小.具体可搜索“空洞卷积”


print(conv.weight.data.size())
## 	conv.weight.data.size()的返回值:
#		# (num_kernels, num_filters_perkernel, (Depth,) Height, Width)
# 		#	i.e.:(out_channels, in_channels/group, kernel_size)

# 影响权重数目的因素有:
# 欲输出featurecube的个数,直接影响卷积核的个数(相等)
# 输入的通道数与设定的该层group数, 多通道卷积会导致与某输出值相关的卷积核成倍增加
# 每个卷积核的尺寸

# ————————————————————————
conv.weight.data = torch.from_numpy(np.ones(24, dtype=np.float32).reshape(6, 2, 2, 1, 1))
# 替换权重值便于观察输出
print(conv.weight.data)

output = conv(x)
print('output=', output.data)
print('outputsize=', output.data.size())
# output.data.size()的返回值:
# 	(batch, out_channels/ or num_of_featurecube, size_of_featurecube)