# 残差网络ResNet

resnet是何凯明大神在2015年提出的.并且获得了当年的ImageNet比赛的冠军. 残差网络具有里程碑的意义,为以后的网络设计提出了一个新的思路.

## 实现残差结构

resnet采取了和vgg类似的堆叠结构,只不过vgg堆叠的是连续卷积核,resnet堆叠的是连续残差块.和vgg一样,越往后面的层,channel相较于前面的layer翻倍,h,w减半.

• 第一个卷积需要传入stride完成下采样
• 卷积后改变了输入shape的话,为了完成相加的操作,需要对输入做1x1卷积
class Residual(nn.Module):
def __init__(self,in_channels,out_channels,stride=1):
super(Residual,self).__init__()
self.stride = stride
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
self.bn2 = nn.BatchNorm2d(out_channels)

#　ｘ卷积后shape发生改变,比如:x:[1,64,56,56] --> [1,128,28,28],则需要1x1卷积改变x
if in_channels != out_channels:
self.conv1x1 = nn.Conv2d(in_channels,out_channels,kernel_size=1,stride=stride)
else:
self.conv1x1 = None

def forward(self,x):
# print(x.shape)
o1 = self.relu(self.bn1(self.conv1(x)))
# print(o1.shape)
o2 = self.bn2(self.conv2(o1))
# print(o2.shape)

if self.conv1x1:
x = self.conv1x1(x)

out = self.relu(o2 + x)
return out


class ResNet(nn.Module):
def __init__(self,in_channels,num_classes):
super(ResNet,self).__init__()
self.conv1 = nn.Sequential(
nn.BatchNorm2d(64),
nn.ReLU(inplace=True)
)

self.conv2 = nn.Sequential(
Residual(64,64),
Residual(64,64),
Residual(64,64),
)

self.conv3 = nn.Sequential(
Residual(64,128,stride=2),
Residual(128,128),
Residual(128,128),
Residual(128,128),
Residual(128,128),
)

self.conv4 = nn.Sequential(
Residual(128,256,stride=2),
Residual(256,256),
Residual(256,256),
Residual(256,256),
Residual(256,256),
Residual(256,256),
)

self.conv5 = nn.Sequential(
Residual(256,512,stride=2),
Residual(512,512),
Residual(512,512),
)

# self.avg_pool = nn.AvgPool2d(kernel_size=7)
self.fc = nn.Linear(512,num_classes)

def forward(self,x):
out = self.conv1(x)
out = self.conv2(out)
out = self.conv3(out)
out = self.conv4(out)
out = self.conv5(out)

out = self.avg_pool(out)
out = out.view((x.shape[0],-1))

out = self.fc(out)

return out


## 数据加载

batch_size,num_workers=32,2


## 模型定义

net = ResNet(1,10).cuda()


## 损失函数定义

l = nn.CrossEntropyLoss()


## 优化器定义

opt = torch.optim.Adam(net.parameters(),lr=0.01)


## 评估函数定义

num_epochs=5
def test():
acc_sum = 0
batch = 0
for X,y in test_iter:
X,y = X.cuda(),y.cuda()
y_hat = net(X)
acc_sum += (y_hat.argmax(dim=1) == y).float().sum().item()
batch += 1

test_acc = acc_sum/(batch*batch_size)

# print('test acc:%f' % test_acc)
return test_acc


## 训练

def train():
for epoch in range(num_epochs):
train_l_sum,batch,train_acc_sum=0,1,0
start = time.time()
for X,y in train_iter:
X,y = X.cuda(),y.cuda() #把tensor放到显存
y_hat = net(X)  #前向传播
loss = l(y_hat,y) #计算loss,nn.CrossEntropyLoss中会有softmax的操作
loss.backward()#反向传播,求出梯度
opt.step()#根据梯度,更新参数

#　数据统计
train_l_sum += loss.item()
train_acc_sum += (y_hat.argmax(dim=1) == y).float().sum().item()
train_loss = train_l_sum/(batch*batch_size)
train_acc = train_acc_sum/(batch*batch_size)

if batch % 100 == 0: #每100个batch输出一次训练数据
print('epoch %d,batch %d,train_loss %.3f,train_acc:%.3f' % (epoch,batch,train_loss,train_acc))

if batch % 300 == 0: #每300个batch测试一次
test_acc = test()
print('epoch %d,batch %d,test_acc:%.3f' % (epoch,batch,test_acc))

batch += 1

end = time.time()
time_per_epoch =  end - start
print('epoch %d,batch_size %d,train_loss %f,time %f' %
(epoch + 1,batch_size ,train_l_sum/(batch*batch_size),time_per_epoch))
test()

train()


load data done,batch_size:32
epoch 0,batch 100,train_loss 0.082,train_acc:0.185
epoch 0,batch 200,train_loss 0.065,train_acc:0.297
epoch 0,batch 300,train_loss 0.053,train_acc:0.411
epoch 0,batch 300,test_acc:0.684
epoch 0,batch 400,train_loss 0.046,train_acc:0.487
epoch 0,batch 500,train_loss 0.041,train_acc:0.539
epoch 0,batch 600,train_loss 0.038,train_acc:0.578
epoch 0,batch 600,test_acc:0.763
epoch 0,batch 700,train_loss 0.035,train_acc:0.604
epoch 0,batch 800,train_loss 0.033,train_acc:0.628
epoch 0,batch 900,train_loss 0.031,train_acc:0.647
epoch 0,batch 900,test_acc:0.729
epoch 0,batch 1000,train_loss 0.030,train_acc:0.661
epoch 0,batch 1100,train_loss 0.029,train_acc:0.674
epoch 0,batch 1200,train_loss 0.028,train_acc:0.686
epoch 0,batch 1200,test_acc:0.802
epoch 0,batch 1300,train_loss 0.027,train_acc:0.696

posted @ 2020-01-17 16:57  core!  阅读(4997)  评论(1编辑  收藏  举报