監督學習:
對已標記的訓練樣本進行學習,然後對樣本的數據進行標記預測。
比如分類垃圾郵件,需對訓練樣本的郵件進行標記,所謂標定,就是每一封郵件都要人爲去制定,然後通過學習,模型對新來的郵件判斷是否是垃圾郵件。
非監督學習:
對沒有標記的訓練樣本進行學習,發現其中的結構性知識。
比如把進店購買商品的顧客進行聚類,將他們劃分成不同的細分市場。
強化學習:
可以理解爲一個機器人不斷依據環境做決策,然後環境根據決策進行獎勵或懲罰,機器人就能根據環境給予的反饋學習的方式。
比如小時候,你放學回家沒有做作業就出去玩,然後就被媽媽教訓了,第二次又這樣,又被教訓了,第三次你就會根據前面的反饋知道應該先做作業,然後媽媽就獎勵了你一個糖果,接着第四次你就會先做作業,這就是一個強化學習的過程舉例。
線性模型:
一元線性模型非常簡單,假設我們有變量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次後,擬合的線和真實的線已經完全重和。