【吴恩达课后编程作业pytorch实现】Keras入门与残差网络的搭建【1】

直接上全部代码。

几个注意点:

  1. 整体的代码是在Colab上写的,前面因为要导入数据,所以引入一些了用不到的包。
  2. .该代码主要是根据原keras的实现代码改变而来,因为框架的不同,做了几点改动,改动中比较重要的地方如下。
    1. 维度处理格式不同,keras中数据处理是类似(num,64,64,3)的,而pytorch是类似(num,3,64,64)的,所以这里要用np.transpose()方法处理数据
    2. loss函数的选择,pytorch里的交叉熵损失函数好像是多元的,感觉不太合适,所以我换了均方差公式做为loss function
  3. 代码中有部分采用了《动手深度学习》书上的代码,我把代码都直接贴出来了,对于新手可能会看不懂这部分,这里做一个备注:
    1. evaluate_accuracy()这个方法是用来计算精确度的,由于pytorch里没有直接算精确度的方法,每次都写又麻烦,所以我一般会用这个函数进行代替,里面精确度具体计算的那行代码,则要根据需求自己改。
    2. train_ch5()方法其实就是训练的函数,复用度也比较高,觉得代码很难看的话,可以直接理解模型的训练过程
  4. 代码是使用GPU跑的,所以有部分代码会显得有点麻烦,涉及到device部分的,可以直接忽略不看
  5. 想看Colab版本的话,直接进https://colab.research.google.com/drive/1ph5TMSn6N_kNFUsgUGfwPlWdMqy0ncPK(要翻墙)。

``

# -*- coding: utf-8 -*-
"""Untitled1.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1ph5TMSn6N_kNFUsgUGfwPlWdMqy0ncPK
"""

!git clone https://github.com/zp2388/AndrewNg-DeepLearning.git

cd /content/AndrewNg-DeepLearning/Lesson4/week2/ResNets

# Commented out IPython magic to ensure Python compatibility.
import numpy as np
from keras import layers
from keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D
from keras.models import Model, load_model
from keras.preprocessing import image
from keras.utils import layer_utils
from keras.utils.data_utils import get_file
from keras.applications.imagenet_utils import preprocess_input
import pydot
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.utils import plot_model
from resnets_utils import *
from keras.initializers import glorot_uniform
import scipy.misc
from matplotlib.pyplot import imshow
# %matplotlib inline

import keras.backend as K
K.set_image_data_format('channels_last')
K.set_learning_phase(1)

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()

type(X_train_orig)

X_train = np.transpose(X_train_orig, (0, 3, 1, 2))/255          # 将维度转为(1080, 3, 64, 64)
X_test = np.transpose(X_test_orig, (0, 3, 1, 2))/255            # 将维度转为(120, 3, 64, 64)

X_train.shape

Y_train = Y_train_orig.T                    # (1080, 1)
Y_test = Y_test_orig.T                      # (120, 1)

import torch
from torch import nn
import os
import sys
import time
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print(torch.__version__)
print(device)

X_train_torch = torch.from_numpy(X_train).float()
y_train_torch = torch.from_numpy(Y_train).float()
X_test_torch = torch.from_numpy(X_test).float()
y_test_torch = torch.from_numpy(Y_test).float()

train_set=torch.utils.data.TensorDataset(X_train_torch,y_train_torch)
test_set=torch.utils.data.TensorDataset(X_test_torch,y_test_torch)

batch_size=1 #本次图片只有600个,所以直接全部随机梯度下降即可

num_workers=0
#这段代码是抄《动手深度学习》的
if sys.platform.startswith('win'):
    num_workers = 0  # 0表示不用额外的进程来加速读取数据
else:
    num_workers = 4

train_iter=torch.utils.data.DataLoader(train_set,batch_size=batch_size,shuffle=True,num_workers=num_workers)
test_iter=torch.utils.data.DataLoader(test_set,batch_size=batch_size,shuffle=True,num_workers=num_workers)

class Net(nn.Module):
  def __init__(self):
    super(Net,self).__init__()
    self.conv1= nn.Sequential(
        nn.Conv2d(in_channels=3,out_channels=32,kernel_size=7,stride=1,padding=3),
        nn.BatchNorm2d(32,affine=True),
        nn.ReLU(),
        nn.MaxPool2d(2,2)
    )
    self.fc= nn.Sequential(
        nn.Flatten(),
        nn.Linear(32768,1)
    )
  def forward(self,x):
    features = self.conv1(x)
    output = self.fc(features)
    return output

net = Net()
print(net)

#以下根据《动手深度学习》代码进行修正
def evaluate_accuracy(data_iter, net, device=None):
    if device is None and isinstance(net, torch.nn.Module):
        # 如果没指定device就使用net的device
        device = list(net.parameters())[0].device 
    acc_sum, n = 0.0, 0
    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(net, torch.nn.Module):
                net.eval() # 评估模式, 这会关闭dropout
                acc_sum += ((net(X.to(device))>=0.5) == (y.to(device)>=0.5)).float().sum().cpu().item()
                net.train() # 改回训练模式
            else: # 自定义的模型, 3.13节之后不会用到, 不考虑GPU
                acc_sum = n
                # if('is_training' in net.__code__.co_varnames): # 如果有is_training这个参数
                #     # 将is_training设置成False
                #     acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item() 
                # else:
                #     acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() 
            n += y.shape[0]
    return acc_sum / n

# Commented out IPython magic to ensure Python compatibility.
#以下根据《动手深度学习》代码进行修正
def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
    net = net.to(device)
    print("training on ", device)
    loss = nn.MSELoss()
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()
        for X, y in train_iter:
            X = X.to(device)
            y = y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            train_l_sum += l.cpu().item()
            train_acc_sum += ((net(X.to(device))>=0.5) == (y.to(device)>=0.5)).float().sum().cpu().item()
            n += y.shape[0]
            batch_count += 1
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
#               % (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))

lr, num_epochs = 0.001, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值