機器學習,深度學習相關概念,及用PyTorch實現(一)

監督學習:

對已標記的訓練樣本進行學習,然後對樣本的數據進行標記預測。

比如分類垃圾郵件,需對訓練樣本的郵件進行標記,所謂標定,就是每一封郵件都要人爲去制定,然後通過學習,模型對新來的郵件判斷是否是垃圾郵件。

非監督學習:

對沒有標記的訓練樣本進行學習,發現其中的結構性知識。

比如把進店購買商品的顧客進行聚類,將他們劃分成不同的細分市場。

強化學習:

可以理解爲一個機器人不斷依據環境做決策,然後環境根據決策進行獎勵或懲罰,機器人就能根據環境給予的反饋學習的方式。

比如小時候,你放學回家沒有做作業就出去玩,然後就被媽媽教訓了,第二次又這樣,又被教訓了,第三次你就會根據前面的反饋知道應該先做作業,然後媽媽就獎勵了你一個糖果,接着第四次你就會先做作業,這就是一個強化學習的過程舉例。


線性模型:

一元線性模型非常簡單,假設我們有變量xi和目標Yi,每個i對應於一個數據點,希望建立一個模型

yi是我們預測的結果,希望通過yi來擬合目標Yi,通俗來講就是找到這個函數擬合Yi使得誤差最小,即最小化

減小這個誤差,需要用到梯度下降

梯度下降:

什麼是梯度?梯度就是導數。如果是一個多元函數,那麼梯度就是偏導數。比如一個函數是f(x,y),那麼梯度就是:

 

我們可以來看一個直觀的解釋。比如我們在一座大山上的某處位置,由於我們不知道怎麼下山,於是決定走一步算一步,也就是在每走到一個位置的時候,求解當前位置的梯度,沿着梯度的負方向,也就是當前最陡峭的位置向下走一步,然後繼續求解當前位置梯度,向這一步所在位置沿着最陡峭最易下山的位置走一步。這樣一步步的走下去,一直走到覺得我們已經到了山腳。當然這樣走下去,有可能我們不能走到山腳,而是到了某一個局部的山峯低處。
類比我們的問題,就是沿着梯度的反方向,我們不斷改變w和b的值,最終找到一組最好的w和b使得誤差最小。
 

在更新的時候,我們需要決定每次更新的幅度,比如在下山的例子中,我們需要每次往下走的那一步的長度,這個長度稱爲學習率,用η表示,這個學習率非常重要,不同的學習率都會導致不同的結果,學習率太小會導致下降非常緩慢,學習率太大又會導致跳動非常明顯。


通過不斷的迭代更新,找到最優的w和b

PyTorch實現線性模型和梯度下降

import torch
import numpy as np
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(2020)

#讀入數據x和y
x_train=np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.799],
                  [6.182],[7.59],[2.167],[7.042],[10.791],
                  [5.313],[7.997],[3.1]],dtype=np.float32)
y_train=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],
                  [3.366],[2.596],[2.53],[1.221],[2.827],
                  [3.465],[1.65],[2.904],[1.3]],dtype=np.float32)

#畫出圖像
plt.plot(x_train,y_train,'bo')
plt.show()

 

 

import torch
import numpy as np
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(2020)

#讀入數據x和y
x_train=np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.799],
                  [6.182],[7.59],[2.167],[7.042],[10.791],
                  [5.313],[7.997],[3.1]],dtype=np.float32)
y_train=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],
                  [3.366],[2.596],[2.53],[1.221],[2.827],
                  [3.465],[1.65],[2.904],[1.3]],dtype=np.float32)

#畫出圖像
plt.plot(x_train,y_train,'bo')
plt.show()

#轉化成Tensor
x_train=torch.from_numpy(x_train)
y_train=torch.from_numpy(y_train)

#定義參數w和b
w=Variable(torch.randn(1),requires_grad=True)#隨機初始化
b=Variable(torch.zeros(1),requires_grad=True)#使用0進行初始化

#構建線性迴歸模型
x_train=Variable(x_train)
y_train=Variable(y_train)

def linear_model(x):
    return x*w+b
y_=linear_model(x_train)

#模型輸出結果:
plt.plot(x_train.data.numpy(),y_train.data.numpy(),'bo',label="real")
plt.plot(x_train.data.numpy(),y_.data.numpy(),'ro',label="estimated")
plt.legend()
plt.show()

紅色的點表示預測值,似乎排列成一條直線,這時候我們需要計算誤差函數:

 

#計算誤差
def get_loss(y_,y):
    return torch.mean((y_-y_train)**2)
loss=get_loss(y_,y_train)
#打印一下看看loss的大小
print(loss)

接下來計算w和b的梯度:

 

import torch
import numpy as np
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(2020)

#讀入數據x和y
x_train=np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.799],
                  [6.182],[7.59],[2.167],[7.042],[10.791],
                  [5.313],[7.997],[3.1]],dtype=np.float32)
y_train=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],
                  [3.366],[2.596],[2.53],[1.221],[2.827],
                  [3.465],[1.65],[2.904],[1.3]],dtype=np.float32)

#畫出圖像
plt.plot(x_train,y_train,'bo')
plt.show()

#轉化成Tensor
x_train=torch.from_numpy(x_train)
y_train=torch.from_numpy(y_train)

#定義參數w和b
w=Variable(torch.randn(1),requires_grad=True)#隨機初始化
b=Variable(torch.zeros(1),requires_grad=True)#使用0進行初始化

#構建線性迴歸模型
x_train=Variable(x_train)
y_train=Variable(y_train)

def linear_model(x):
    return x*w+b
y_=linear_model(x_train)

#計算誤差
def get_loss(y_,y):
    return torch.mean((y_-y_train)**2)
loss=get_loss(y_,y_train)
#打印一下看看loss的大小
print(loss)

#自動求導
loss.backward()
#查看w和b的梯度
print(w.grad)
print(b.grad)

#更新一次參數
w.data=w.data-1e-2*w.grad.data
b.data=b.data-1e-2*b.grad.data

#更新參數後,查看時輸出模型
y_=linear_model(x_train)
plt.plot(x_train.data.numpy(),y_train.data.numpy(),'bo',label="real")
plt.plot(x_train.data.numpy(),y_.data.numpy(),'ro',label="estimated")
plt.legend()
plt.show()

 

從上面的例子可以看到,更新之後紅色的線跑到了藍色的線下面,沒有特別好的擬合藍色的真實值,所以需要在進行幾次更新。
 

 

import torch
import numpy as np
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(2020)

#讀入數據x和y
x_train=np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.799],
                  [6.182],[7.59],[2.167],[7.042],[10.791],
                  [5.313],[7.997],[3.1]],dtype=np.float32)
y_train=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],
                  [3.366],[2.596],[2.53],[1.221],[2.827],
                  [3.465],[1.65],[2.904],[1.3]],dtype=np.float32)

#轉化成Tensor
x_train=torch.from_numpy(x_train)
y_train=torch.from_numpy(y_train)

#定義參數w和b
w=Variable(torch.randn(1),requires_grad=True)#隨機初始化
b=Variable(torch.zeros(1),requires_grad=True)#使用0進行初始化

#構建線性迴歸模型
x_train=Variable(x_train)
y_train=Variable(y_train)

def linear_model(x):
    return x*w+b
y_=linear_model(x_train)

#計算誤差
def get_loss(y_,y):
    return torch.mean((y_-y_train)**2)
loss=get_loss(y_,y_train)
#打印一下看看loss的大小
print(loss)
#自動求導
loss.backward()

for e in range(10):#進行10次更新
    y_=linear_model(x_train)
    loss=get_loss(y_,y_train)
    w.grad.zero_()#記得歸零梯度
    b.grad.zero_()#記得歸零梯度
    loss.backward()
    # 更新參數
    w.data = w.data - 1e-2 * w.grad.data
    b.data = b.data - 1e-2 * b.grad.data
    print('epoch:{},loss:{}'.format(e,loss.data))


y_=linear_model(x_train)
plt.plot(x_train.data.numpy(),y_train.data.numpy(),'bo',label="real")
plt.plot(x_train.data.numpy(),y_.data.numpy(),'ro',label="estimated")
plt.legend()
plt.show()

 

經過10次更新,我們發現紅色的預測結果已經比較好的擬合了藍色的真實值。
 

多項式迴歸模型:

import matplotlib.pyplot as plt
import numpy as np
import torch
from torch.autograd import Variable

w_target=np.array([0.5,3,2.4])#定義參數
b_target=np.array([0.9])#定義參數

f_des='y={:.2f}+{:.2f}*x+{:.2f}*x^2+{:.2f}*x^3'.format(
    b_target[0],w_target[0],w_target[1],w_target[2]
)
#打印出函數的式子
print(f_des)

#畫出多項式圖像
x_sample=np.arange(-3,3.1,0.1)
y_sample=b_target[0]+w_target[0]*x_sample+w_target[1]*x_sample**2+w_target[2]*x_sample**3

plt.plot(x_sample,y_sample,label="real curve")
plt.legend()
plt.show()

#構建數據階,需要x和y,同時是一個三次多項式
x_train=np.stack([x_sample**i for i in range(1,4)],axis=1)
x_train=torch.from_numpy(x_train).float()#轉化成float tensor

y_train=torch.from_numpy(y_sample).float().unsqueeze(1)

#定義參數和模型
w=Variable(torch.rand(3,1),requires_grad=True)
b=Variable(torch.rand(1),requires_grad=True)

#將x和y轉化成Variable
x_train=Variable(x_train)
y_train=Variable(y_train)

def multi_linear(x):
    return torch.mm(x,w)+b

#畫出沒有更新之前的模型
y_pred=multi_linear(x_train)

plt.plot(x_train.data.numpy()[:,0],y_pred.data.numpy(),label="fitting curve",color="r")
plt.plot(x_train.data.numpy()[:,0],y_sample,label="real curve",color="b")
plt.legend()
plt.show()

#計算誤差
#計算誤差
def get_loss(y_,y):
    return torch.mean((y_-y_train)**2)
loss=get_loss(y_pred,y_train)
print(loss)

#自動求導
loss.backward()
#查看一下w和b的梯度
print(w.grad)
print(b.grad)

#更新一下參數
y_pred=multi_linear(x_train)
plt.plot(x_train.data.numpy()[:,0],y_pred.data.numpy(),label="fitting curve",color="r")
plt.plot(x_train.data.numpy()[:,0],y_sample,label="real curve",color="b")
plt.legend()
plt.show()

for e in range(100):#進行100次更新
    y_pred=multi_linear(x_train)
    loss=get_loss(y_pred,y_train)

    w.grad.zero_()#記得歸零梯度
    b.grad.zero_()#記得歸零梯度
    loss.backward()
    # 更新參數
    w.data = w.data - 0.001 * w.grad.data
    b.data = b.data - 0.001 * b.grad.data
    if(e+1)%20==0:
        print('epoch:{},loss:{}'.format(e,loss.data))


y_pred=multi_linear(x_train)
plt.plot(x_train.data.numpy()[:,0],y_pred.data.numpy(),label="fitting curve",color="r")
plt.plot(x_train.data.numpy()[:,0],y_sample,label="real curve",color="b")
plt.legend()
plt.show()

 打印出函數的式子

 

畫出多項式的圖像

更新之前的模型 

 

 

 更新一次之後的模型

 

 

更新100次後,擬合的線和真實的線已經完全重和。

 

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