pytorch 實現簡單二元分類器以及可視化

這個文章是用pytorch和matplotlib實現一個二元分類器而且可視化。python

思路

  1. 本身生成兩團數據。
  2. 定義本身的神經網絡類。
  3. 訓練網絡
  4. 打印出邊界。

先放效果圖

image

關於可視化

定義網絡、訓練網絡主要沒什麼好說的啦其實,畢竟有pytorch這麼好的框架,已經提供瞭如此簡單的代碼工做。網絡

主要是可視化的技巧。框架

主要是matplotlib中有個contourf,自己是畫等高線用的,就是地理中那個三維圖投射到二維圖的那種圖。函數

咱們能夠把這個用到可視化上來(固然只是3維的,若是是更高維度就無法用這個可視化了)。spa

具體怎麼可視化的?

首先,先本身生成200個訓練數據(這步對應getData函數),而後把屬於不一樣類別的數據染上不一樣顏色;
而後,進行網絡的訓練(對應run函數);
而後,用一樣的數據讓網絡進行預測。由於二元分類器最後預測的結果要麼是0,要麼是1,因此能夠利用matplotlib中的畫等高線的函數,來近似畫出決策邊界。這一步主要對應showBoundary函數。code

使用conturf函數

這個函數我本身在用的時候有點懵逼,使用這個要先meshgrid,mesh合併的意思,grid網格的意思,要把兩個列表先合成一個網格,這個形式我也不是很喜歡。
勉勉強強參考了一些博客才寫了出來。具體我也沒辦法一一講述,還請各位原諒。
不過其中,cmap是畫出來的圖的風格參數,能夠是camp=plt.cm.hot等等,alpha是透明度。orm

用了conturf這個函數,就能夠有顏色的區別了。blog

最後放代碼

import torch
import torch.nn.modules
import torch.nn
import numpy as np
from torch.autograd import Variable #torch的基本變量
import torch.nn.functional as F #裏面有不少torch的函數
import matplotlib.pyplot as plt
 
 
#定義自帶forward propagation的神經網絡。
class Net(torch.nn.Module):
    def __init__(self,n_features,n_hiddens,n_outputs):
        super(Net,self).__init__()
        self.hidden=torch.nn.Linear(n_features,n_hiddens)
        self.predict=torch.nn.Linear(n_hiddens,n_outputs)
 
    def forward(self, x):
        x=F.relu(self.hidden(x))
        predict=F.softmax(self.predict(x))
        return predict

class MyNet:
    def __init__(self,n_features,n_hiddens,n_outputs,times):
        self.NeuronalNet=Net(n_features,n_hiddens,n_outputs)
        self.realX=None
        self.realY=None
        self.opitimizer=None
        self.lossFunc=None
        self.times=times
    #訓練集
    def getData(self):
        temp = torch.ones(100, 2)
 
        B = torch.normal(2 * temp, 1)
 
        By = torch.ones(100)
        A = torch.normal(-2 * temp, 1)
        Ay = torch.zeros(100)
 
        self.realX = Variable(torch.cat([A, B], 0))
        self.realY = Variable(torch.cat([Ay, By]).type(torch.LongTensor))
 
        # plt.scatter(realX.data.numpy()[:,0],realX.data.numpy()[:,1],c=realY)
        # plt.show()
 
 
 
    def run(self):
        self.opitimizer=torch.optim.SGD(self.NeuronalNet.parameters(),lr=0.01)
        self.lossFunc=torch.nn.CrossEntropyLoss()
 
        for i in range(self.times):
            out=self.NeuronalNet(self.realX)
 
            loss=self.lossFunc(out,self.realY)
 
            self.opitimizer.zero_grad()
 
            loss.backward()
 
            self.opitimizer.step()
 
 
    #可視化
    def showBoundary(self):
        x_min, x_max = self.realX[:, 0].min() - 0.1, self.realX[:, 0].max() + 0.1
        y_min, y_max = self.realX[:, 1].min() - 0.1, self.realX[:, 1].max() + 0.1
        xx, yy = np.meshgrid(np.linspace(x_min, x_max, 101), np.linspace(y_min, y_max, 101))
        cmap = plt.cm.Spectral
 
        X_test = torch.from_numpy(np.c_[xx.ravel(), yy.ravel()]).float()
        y_pred = self.NeuronalNet(X_test)
        _, y_pred = y_pred.max(dim=1)
        y_pred = y_pred.reshape(xx.shape)
 
        plt.contourf(xx, yy, y_pred, cmap=plt.cm.Spectral, alpha=0.8)
        plt.scatter(self.realX[:, 0], self.realX[:, 1], c=self.realY, s=40, cmap=plt.cm.RdYlBu)
        plt.xlim(xx.min(), xx.max())
        plt.ylim(yy.min(), yy.max())
        plt.title("binary classifier")
        plt.show()
 
    def predict(self,inputData):
        #inputData should be a 1x2 matrix
        data=torch.from_numpy(np.array(inputData)).int()
        return self.NeuronalNet(data.float())
 
if __name__=="__main__":
 
    myNet =MyNet(2,18,2,1000)
    myNet.getData()
    myNet.run()
    myNet.showBoundary()
    probabilitys=list(myNet.predict([3, 3]).data.numpy())
    print("是第{0}類".format(1+probabilitys.index(max(probabilitys))))
相關文章
相關標籤/搜索