PyTorch學習:多層神經網絡的多種實現方式

import torch
import numpy as np
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
def plot_decision_boundary(model, x, y):
    # Set min and max values and give it some padding
    x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
    y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole grid
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(x[:, 0], x[:, 1], c=y.reshape(-1), s=40, cmap=plt.cm.Spectral)
def draw_picture():    
    np.random.seed(1)
    m = 400 # 樣本數量
    N = int(m/2) # 每一類的點的個數
    D = 2 # 維度
    x = np.zeros((m, D))
    y = np.zeros((m, 1), dtype='uint8') # label 向量,0 表示紅色,1 表示藍色
    a = 4
    for j in range(2):
        ix = range(N*j,N*(j+1))
        t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
        r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
        x[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
        y[ix] = j
    plt.scatter(x[:, 0], x[:, 1], c=y.reshape(-1), s=40, cmap=plt.cm.Spectral)
    plt.show()
    plt.close()
    return x,y
def logistic_regression(x,w,b):
    return torch.mm(x, w) + b
def plot_logistic(x,w,b):
    x = Variable(torch.from_numpy(x).float())
    out = F.sigmoid(logistic_regression(x,w,b))
    out = (out > 0.5) * 1
    return out.data.numpy()
def logistic_train(x,y):
    x = torch.from_numpy(x).float()
    y = torch.from_numpy(y).float()
    w = nn.Parameter(torch.randn(2, 1))
    b = nn.Parameter(torch.zeros(1))
    optimizer = torch.optim.SGD([w, b], 1e-1)

    criterion = nn.BCEWithLogitsLoss()
    
    for e in range(100):
        out = logistic_regression(Variable(x),w,b)
        loss = criterion(out, Variable(y))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if (e + 1) % 20 == 0:
            print('epoch: {}, loss: {}'.format(e+1, loss.item()))
    plot_decision_boundary(lambda x: plot_logistic(x,w,b), x.numpy(), y.numpy())
    plt.title('logistic regression')
    plt.show()
    plt.close()
def two_network_train(x,y):
    # 定義兩層神經網絡的參數
    w1 = nn.Parameter(torch.randn(2, 4) * 0.01) # 隱藏層神經元個數 2
    b1 = nn.Parameter(torch.zeros(4))
    
    w2 = nn.Parameter(torch.randn(4, 1) * 0.01)
    b2 = nn.Parameter(torch.zeros(1))
    
    # 定義模型
    def two_network(x):
        x1 = torch.mm(x, w1) + b1
        x1 = F.tanh(x1) # 使用 PyTorch 自帶的 tanh 激活函數
        x2 = torch.mm(x1, w2) + b2
        return x2
    x = torch.from_numpy(x).float()
    y = torch.from_numpy(y).float()
    optimizer = torch.optim.SGD([w1, w2, b1, b2], 1.)
    criterion = nn.BCEWithLogitsLoss()
    # 我們訓練 10000 次
    for e in range(10000):
        out = two_network(Variable(x))
        loss = criterion(out, Variable(y))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if (e + 1) % 1000 == 0:
            print('epoch: {}, loss: {}'.format(e+1, loss.item()))
    def plot_network(x):
        x = Variable(torch.from_numpy(x).float())
        x1 = torch.mm(x, w1) + b1
        x1 = F.tanh(x1)
        x2 = torch.mm(x1, w2) + b2
        out = F.sigmoid(x2)
        out = (out > 0.5) * 1
        return out.data.numpy()
    plot_decision_boundary(lambda x: plot_network(x), x.numpy(), y.numpy())
    plt.title('2 layer network')
    plt.show()
    plt.close()
def sequential_train(x,y):
    x = torch.from_numpy(x).float()
    y = torch.from_numpy(y).float()
    # Sequential
    seq_net = nn.Sequential(
        nn.Linear(2, 4), # PyTorch 中的線性層,wx + b
        nn.Tanh(),
        nn.Linear(4, 1)
    )
    # 通過 parameters 可以取得模型的參數
    param = seq_net.parameters()
    
    criterion = nn.BCEWithLogitsLoss()
    # 定義優化器
    optim = torch.optim.SGD(param, 1.)
    # 我們訓練 10000 次
    for e in range(10000):
        out = seq_net(Variable(x))
        loss = criterion(out, Variable(y))
        optim.zero_grad()
        loss.backward()
        optim.step()
        if (e + 1) % 1000 == 0:
            print('epoch: {}, loss: {}'.format(e+1, loss.item()))
    def plot_seq(x):
        out = F.sigmoid(seq_net(Variable(torch.from_numpy(x).float()))).data.numpy()
        out = (out > 0.5) * 1
        return out
    plot_decision_boundary(lambda x: plot_seq(x), x.numpy(), y.numpy())
    plt.title('sequential') 
    plt.show()
    plt.close()   
    
    
    #兩種保存模型的辦法
    # 1.將參數和模型保存在一起
    torch.save(seq_net, 'save_seq_net.pth')
    # 2.保存模型參數
    torch.save(seq_net.state_dict(), 'save_seq_net_params.pth')
def load_moudle():
    # 讀取保存的模型
    seq_net1 = torch.load('save_seq_net.pth')
    print(seq_net1)
    print(seq_net1[0].weight)
    seq_net2 = nn.Sequential(
      nn.Linear(2, 4),
      nn.Tanh(),
      nn.Linear(4, 1)
    )
    seq_net2.load_state_dict(torch.load('save_seq_net_params.pth'))  
    print(seq_net2)
    print(seq_net2[0].weight)
def module_train(x,y):
    class module_net(nn.Module):
        def __init__(self, num_input, num_hidden, num_output):
            super(module_net, self).__init__()
            self.layer1 = nn.Linear(num_input, num_hidden)
            
            self.layer2 = nn.Tanh()
            
            self.layer3 = nn.Linear(num_hidden, num_output)
            
        def forward(self, x):
            x = self.layer1(x)
            x = self.layer2(x)
            x = self.layer3(x)
            return x
    x = torch.from_numpy(x).float()
    y = torch.from_numpy(y).float()
    mo_net = module_net(2, 4, 1)    
    optim = torch.optim.SGD(mo_net.parameters(), 1.)
    criterion = nn.BCEWithLogitsLoss()
    # 我們訓練 10000 次
    for e in range(10000):
        out = mo_net(Variable(x))
        loss = criterion(out, Variable(y))
        optim.zero_grad()
        loss.backward()
        optim.step()
        if (e + 1) % 1000 == 0:
            print('epoch: {}, loss: {}'.format(e+1, loss.item()))
if __name__ == "__main__":
    x,y=draw_picture()
    logistic_train(x,y)# 自定義兩層神經網絡
    sequential_train(x,y)# 定義sequential神經網絡
    load_moudle()
    module_train(x,y)# 定義module神經網絡

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章