0


机器学习基础备忘录

本文侧重代码实现,不讨论原理。

github图床出了一点问题,就不插图了。

文章目录

距离计算

     欧
    
    
     氏
    
    
     距
    
    
     离
    
    
     :
    
    
     d
    
    
     (
    
    
     x
    
    
     ,
    
    
     y
    
    
     )
    
    
     =
    
    
     
      
       
        ∑
       
       
        
         k
        
        
         =
        
        
         1
        
       
       
        N
       
      
      
       (
      
      
       
        x
       
       
        k
       
      
      
       −
      
      
       
        y
       
       
        k
       
      
      
       
        )
       
       
        2
       
      
     
    
   
   
     欧氏距离:d(x,y)=\sqrt{\sum_{k=1}^{N}(x_k-y_k)^2} 
   
  
 欧氏距离:d(x,y)=k=1∑N​(xk​−yk​)2​

 
  
   
    
     曼
    
    
     哈
    
    
     顿
    
    
     距
    
    
     离
    
    
     :
    
    
     d
    
    
     (
    
    
     x
    
    
     ,
    
    
     y
    
    
     )
    
    
     =
    
    
     
      ∑
     
     
      
       k
      
      
       =
      
      
       1
      
     
     
      N
     
    
    
     ∣
    
    
     
      x
     
     
      k
     
    
    
     −
    
    
     
      y
     
     
      k
     
    
    
     ∣
    
   
   
     曼哈顿距离:d(x,y)=\sum_{k=1}^N|x_k-y_k| 
   
  
 曼哈顿距离:d(x,y)=k=1∑N​∣xk​−yk​∣

 
  
   
    
     切
    
    
     比
    
    
     雪
    
    
     夫
    
    
     距
    
    
     离
    
    
     :
    
    
     d
    
    
     (
    
    
     x
    
    
     ,
    
    
     y
    
    
     )
    
    
     =
    
    
     max
    
    
     ⁡
    
    
     (
    
    
     ∣
    
    
     
      x
     
     
      k
     
    
    
     −
    
    
     
      y
     
     
      k
     
    
    
     ∣
    
    
     )
    
   
   
     切比雪夫距离:d(x,y)=\max(|x_k-y_k|) 
   
  
 切比雪夫距离:d(x,y)=max(∣xk​−yk​∣)

 
  
   
    
     余
    
    
     弦
    
    
     距
    
    
     离
    
    
     :
    
    
     c
    
    
     o
    
    
     s
    
    
     θ
    
    
     =
    
    
     
      
       
        x
       
       
        1
       
      
      
       
        x
       
       
        2
       
      
      
       +
      
      
       
        y
       
       
        1
       
      
      
       
        y
       
       
        2
       
      
     
     
      
       
        
         
          x
         
         
          1
         
         
          2
         
        
        
         +
        
        
         
          x
         
         
          2
         
         
          2
         
        
       
      
      
       
        
         
          y
         
         
          1
         
         
          2
         
        
        
         +
        
        
         
          y
         
         
          2
         
         
          2
         
        
       
      
     
    
   
   
     余弦距离:cos\theta=\frac{x_1x_2+y_1y_2}{\sqrt{x_1^2+x_2^2}\sqrt{y_1^2+y_2^2}} 
   
  
 余弦距离:cosθ=x12​+x22​​y12​+y22​​x1​x2​+y1​y2​​
import numpy as np

dot1 = np.array([1,2])# 第一个点的坐标(1,2)
dot2 = np.array([4,5])# 第二个点的坐标(4,5)

d1 = np.sqrt(np.sum((dot1-dot2)**2))# 欧氏距离
d2 = np.sum(np.abs(dot1-dot2))# 曼哈顿距离
d3 = np.max(np.abs(dot1-dot2))# 切比雪夫距离
d4 = np.dot(dot1,dot2)/ np.sqrt(np.dot(dot1,dot1)*np.dot(dot2,dot2))# 余弦距离

模型选择

留出法

将数据分为训练集和测试集,使用训练集生成模型,使用测试集检验模型准确率。

# 核心代码
train_test_split(data,data_lable,test_size=0.6)
# 完整代码from sklearn.model_selection import train_test_split
import numpy as np

data = np.array([10,21,23,53,63])# 需要划分的数据
data_lable =[0,1,2,3,4]# 上述数据的标签"""
训练集数据, 测试集数据, 训练集标签, 测试集标签 = 
train_test_split(数据列表,数据列表标签,test_size=训练集/总数)
"""
data_train, data_test, lable_train, lable_test = train_test_split(data,data_lable,test_size=0.6)

交叉验证法

相当于多次

train_test_split

操作。将数据集划分为k个大小相似的子集,每次选取其中一个子集作为测试集,其他数据作为训练集。如[10,20,30,40],我们设k=4,则生成如下4种数据集:

训练集:[10,20,30],测试集:[40]
训练集:[10,20,40],测试集:[30]
训练集:[10,30,40],测试集:[20]
训练集:[20,30,40],测试集:[10]

代码如下:

# 核心代码"""
将data数组分成3折 : KFold(n_splits=3).split(data)  
train_index:训练集索引  使用data[train_index]获取训练集
test_index:测试集索引  使用data[test_index]获取测试集
"""for train_index, test_index in KFold(n_splits=3).split(data):...略...
# 完整代码import numpy as np
from sklearn.model_selection import KFold

data = np.array([10,21,23,53,63,25])# 需要划分的数据for train_index, test_index in KFold(n_splits=3).split(data):print("————————————————————————————————")print("训练集索引:",train_index,"训练集:",data[train_index])print("测试集索引:",test_index,"测试集:",data[test_index])
# 输出
————————————————————————————————
训练集索引:[2345] 训练集:[23536325]
测试集索引:[01] 测试集:[1021]
————————————————————————————————
训练集索引:[0145] 训练集:[10216325]
测试集索引:[23] 测试集:[2353]
————————————————————————————————
训练集索引:[0123] 训练集:[10212353]
测试集索引:[45] 测试集:[6325]

留一法

交叉验证的变种,每次只留一个数据作为测试集。例如有n个数需要被划分,则留一法就相当于k=n的交叉验证。

# 核心代码for train_index, test_index in LeaveOneOut().split(data):...略...
# 完整代码from sklearn.model_selection import LeaveOneOut
import numpy as np

data = np.array([10,20,30,40])for train_index, test_index in LeaveOneOut().split(data):print("————————————————————————————————")print("训练集索引:",train_index,"训练集:",data[train_index])print("测试集索引:",test_index,"测试集:",data[test_index])
# 输出
————————————————————————————————
训练集索引:[123] 训练集:[203040]
测试集索引:[0] 测试集:[10]
————————————————————————————————
训练集索引:[023] 训练集:[103040]
测试集索引:[1] 测试集:[20]
————————————————————————————————
训练集索引:[013] 训练集:[102040]
测试集索引:[2] 测试集:[30]
————————————————————————————————
训练集索引:[012] 训练集:[102030]
测试集索引:[3] 测试集:[40]

性能度量

均方误差MSE

     M
    
    
     S
    
    
     E
    
    
     =
    
    
     
      1
     
     
      n
     
    
    
     
      ∑
     
     
      
       i
      
      
       =
      
      
       1
      
     
     
      n
     
    
    
     (
    
    
     f
    
    
     (
    
    
     
      x
     
     
      i
     
    
    
     )
    
    
     −
    
    
     
      y
     
     
      i
     
    
    
     
      )
     
     
      2
     
    
   
   
     MSE = \frac{1}{n}\sum_{i=1}^{n}(f(x_i)-y_i)^2 
   
  
 MSE=n1​i=1∑n​(f(xi​)−yi​)2

实现如下:

# 核心代码"""
均方误差 = mean_squared_error(真值列表,预测值列表)
"""
result = mean_squared_error(y_true, y_pred)
import numpy as np                            
from sklearn.metrics import mean_squared_error
                                              
y_true = np.array([1,2,3,4,5,6])# 正确数据 
y_pred = np.array([0,2,2,4,5,7])# 预测数据 
                                              
result = mean_squared_error(y_true, y_pred)# result结果为0.5

均方根误差RMSE

     R
    
    
     M
    
    
     S
    
    
     E
    
    
     =
    
    
     
      
       
        1
       
       
        n
       
      
      
       
        ∑
       
       
        
         i
        
        
         =
        
        
         1
        
       
       
        n
       
      
      
       (
      
      
       f
      
      
       (
      
      
       
        x
       
       
        i
       
      
      
       )
      
      
       −
      
      
       
        y
       
       
        i
       
      
      
       
        )
       
       
        2
       
      
     
    
   
   
     RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(f(x_i)-y_i)^2} 
   
  
 RMSE=n1​i=1∑n​(f(xi​)−yi​)2​
# 实现(MSE套一层根号即可)
result = np.sqrt( mean_squared_error(y_true, y_pred))

平均绝对误差MAE

     M
    
    
     A
    
    
     E
    
    
     =
    
    
     
      1
     
     
      n
     
    
    
     
      ∑
     
     
      
       i
      
      
       =
      
      
       1
      
     
     
      m
     
    
    
     ∣
    
    
     f
    
    
     (
    
    
     
      x
     
     
      i
     
    
    
     )
    
    
     −
    
    
     
      y
     
     
      i
     
    
    
     ∣
    
   
   
     MAE = \frac{1}{n}\sum_{i=1}^{m}|f(x_i)-y_i| 
   
  
 MAE=n1​i=1∑m​∣f(xi​)−yi​∣

实现起来非常简单,就是将MSE中的

mean_squared_error

替换成

mean_absolute_error

# 实现import numpy as np                            
from sklearn.metrics import mean_absolute_erro
                                              
y_true = np.array([1,2,3,4,5,6])# 正确数据 
y_pred = np.array([0,2,2,4,5,7])# 预测数据 
                                              
result = mean_absolute_error(y_true, y_pred)

准确率

预测对的 / 所有

     a
    
    
     c
    
    
     c
    
    
     =
    
    
     
      1
     
     
      n
     
    
    
     
      ∑
     
     
      
       i
      
      
       =
      
      
       1
      
     
     
      n
     
    
    
     (
    
    
     f
    
    
     (
    
    
     
      x
     
     
      i
     
    
    
     )
    
    
     =
    
    
     
      y
     
     
      i
     
    
    
     )
    
   
   
     acc=\frac{1}{n}\sum_{i=1}^{n}(f(x_i)=y_i) 
   
  
 acc=n1​i=1∑n​(f(xi​)=yi​)
# 核心代码"""
准确率 = accuracy_score(正确数据列表,预测数据列表)   
"""
result = accuracy_score(y_true,y_pred)
# 完整代码import numpy as np                         
from sklearn.metrics import accuracy_score 
                                           
y_true = np.array([1,2,3,4,5,6])# 正确
y_pred = np.array([0,2,2,4,5,7])# 预测
                                           
result = accuracy_score(y_true,y_pred)

混淆矩阵

真实情况\预测结果正例反例正例TP(真正例)FN(假反例)反例FP(假正例)TN(真反例)

  • 查准率:预测为正中,预测正确的概率 P = T P T P + F P P=\frac{TP}{TP+FP} P=TP+FPTP​
  • 查全率:真实情况为正中,预测正确的概率 R = T P T P + F N R = \frac{TP}{TP+FN} R=TP+FNTP​
  • 准确率 A C C = T P + T N T P + F P + T N + F N ACC = \frac{TP+TN}{TP+FP+TN+FN} ACC=TP+FP+TN+FNTP+TN​

通过生成真实数据与预测数据的混淆矩阵,可以更好的看出预测的情况。

# 核心代码"""
混淆矩阵 = confusion_matrix(真实数据集,预测数据集,labels=标签集) 
此处的标签集不好理解,看下面的样例就懂了
"""
result = confusion_matrix(y_true,y_pred,labels=[0,1])
# 完整代码import numpy as np                                         
from sklearn.metrics import confusion_matrix               
                                                           
y_pred = np.array([0,1,0,1])# 预测数据                       
y_true = np.array([1,0,1,1])# 正确数据                       
                                                           
result = confusion_matrix(y_true,y_pred,labels=[0,1])
# 输出[[01][21]]

上述输出可以用如下表格来解释

此处假设0为正例,1为反例

真实情况\预测结果01001121
以上表格蕴含了以下信息:
真实情况预测结果预测次数结果000真正例TP = 0011假反例FN = 1,预测错误1次102假正例FP = 2,预测错误2次111真反例TN = 1,预测成功1次

     查
    
    
     准
    
    
     率
    
    
     =
    
    
     
      
       T
      
      
       P
      
     
     
      
       T
      
      
       P
      
      
       +
      
      
       F
      
      
       P
      
     
    
    
     =
    
    
     
      0
     
     
      
       0
      
      
       +
      
      
       2
      
     
    
    
     =
    
    
     0
    
   
   
     查准率 = \frac{TP}{TP+FP}=\frac{0}{0+2}=0 
   
  
 查准率=TP+FPTP​=0+20​=0

 
  
   
    
     查
    
    
     全
    
    
     率
    
    
     =
    
    
     
      
       T
      
      
       P
      
     
     
      
       T
      
      
       P
      
      
       +
      
      
       F
      
      
       N
      
     
    
    
     =
    
    
     
      0
     
     
      
       0
      
      
       +
      
      
       1
      
     
    
    
     =
    
    
     0
    
   
   
     查全率 = \frac{TP}{TP+FN}=\frac{0}{0+1}=0 
   
  
 查全率=TP+FNTP​=0+10​=0

 
  
   
    
     准
    
    
     确
    
    
     率
    
    
     =
    
    
     
      
       T
      
      
       P
      
      
       +
      
      
       T
      
      
       N
      
     
     
      
       T
      
      
       P
      
      
       +
      
      
       F
      
      
       P
      
      
       +
      
      
       T
      
      
       N
      
      
       +
      
      
       F
      
      
       N
      
     
    
    
     =
    
    
     
      
       0
      
      
       +
      
      
       1
      
     
     
      
       0
      
      
       +
      
      
       2
      
      
       +
      
      
       1
      
      
       +
      
      
       1
      
     
    
    
     =
    
    
     
      1
     
     
      4
     
    
   
   
     准确率=\frac{TP+TN}{TP+FP+TN+FN}=\frac{0+1}{0+2+1+1} = \frac{1}{4} 
   
  
 准确率=TP+FP+TN+FNTP+TN​=0+2+1+10+1​=41​

实际上,sklearn也提供了直接计算查准率的函数

precision_score
# 查准率import numpy as np
from sklearn.metrics import precision_score

y_pred = np.array([0,1,0,1])# 预测数据
y_true = np.array([1,0,1,1])# 正确数据

accu = precision_score(y_true,y_pred,average='macro')# accu结果为0.25

ROC曲线

真实情况\预测结果正例反例正例TP(真正例)FN(假反例)反例FP(假正例)TN(真反例)

     R
    
    
     O
    
    
     C
    
    
     曲
    
    
     线
    
    
     X
    
    
     轴
    
    
     :
    
    
     f
    
    
     p
    
    
     r
    
    
     =
    
    
     
      
       F
      
      
       P
      
     
     
      
       F
      
      
       P
      
      
       +
      
      
       T
      
      
       N
      
     
    
    
     =
    
    
     
      
       真
      
      
       实
      
      
       情
      
      
       况
      
      
       中
      
      
       :
      
      
       反
      
      
       例
      
      
       预
      
      
       测
      
      
       错
      
      
       误
      
      
       的
      
     
     
      
       真
      
      
       实
      
      
       情
      
      
       况
      
      
       中
      
      
       :
      
      
       反
      
      
       例
      
      
       总
      
      
       和
      
     
    
   
   
     ROC曲线X轴:fpr=\frac{FP}{FP+TN}=\frac{真实情况中:反例预测错误的}{真实情况中:反例总和} 
   
  
 ROC曲线X轴:fpr=FP+TNFP​=真实情况中:反例总和真实情况中:反例预测错误的​

 
  
   
    
     R
    
    
     O
    
    
     C
    
    
     曲
    
    
     线
    
    
     Y
    
    
     轴
    
    
     :
    
    
     t
    
    
     p
    
    
     r
    
    
     (
    
    
     查
    
    
     全
    
    
     率
    
    
     )
    
    
     =
    
    
     
      
       T
      
      
       P
      
     
     
      
       T
      
      
       P
      
      
       +
      
      
       F
      
      
       N
      
     
    
    
     =
    
    
     
      
       真
      
      
       实
      
      
       情
      
      
       况
      
      
       中
      
      
       :
      
      
       正
      
      
       例
      
      
       中
      
      
       预
      
      
       测
      
      
       正
      
      
       确
      
      
       的
      
     
     
      
       真
      
      
       实
      
      
       情
      
      
       况
      
      
       中
      
      
       :
      
      
       正
      
      
       例
      
      
       总
      
      
       和
      
     
    
   
   
     ROC曲线Y轴:tpr(查全率)=\frac{TP}{TP+FN}=\frac{真实情况中:正例中预测正确的}{真实情况中:正例总和} 
   
  
 ROC曲线Y轴:tpr(查全率)=TP+FNTP​=真实情况中:正例总和真实情况中:正例中预测正确的​

在ROC曲线中,AUC(曲线下的面积)值越大,说明该模型性能越好。

# 核心代码"""
x轴列表, y轴列表, _ = roc_curve(真实数据,预测数据)
曲线下面积 = auc(x轴列表, y轴列表)
"""
fpr_x, tpr_y, _ = roc_curve(y_true, y_pred)# 生成ROC曲线的x、y值列表
auc = auc(fpr_x, tpr_y)# 计算曲线下的面积
# 完整代码import numpy as np
from sklearn.metrics import roc_curve, auc

y_pred = np.array([0.1,0.8,0.2,0.5,0.5,0.7,0.3,0.1])# 预测数据
y_true = np.array([0,1,0,1,1,1,0,1])# 正确数据

fpr_x, tpr_y, _ = roc_curve(y_true, y_pred)# 生成ROC曲线的x、y值列表
auc = auc(fpr_x, tpr_y)# 计算曲线下的面积# auc结果为0.8333333333333334

协方差Cov

     C
    
    
     o
    
    
     v
    
    
     (
    
    
     X
    
    
     ,
    
    
     Y
    
    
     )
    
    
     =
    
    
     
      
       
        ∑
       
       
        
         i
        
        
         =
        
        
         1
        
       
       
        n
       
      
      
       (
      
      
       
        x
       
       
        i
       
      
      
       −
      
      
       
        x
       
       
        ‾
       
      
      
       )
      
      
       (
      
      
       
        y
       
       
        i
       
      
      
       −
      
      
       
        y
       
       
        ‾
       
      
      
       )
      
     
     
      
       n
      
      
       −
      
      
       1
      
     
    
   
   
     Cov(X,Y)=\frac{\sum_{i=1}^{n}(x_i-\overline{x})(y_i-\overline{y})}{n-1} 
   
  
 Cov(X,Y)=n−1∑i=1n​(xi​−x)(yi​−y​)​

通过一个实例来计算:

  1. 为方便计算,我们只定义两个点,每个点(样本)有两个特征:x与y

      d
     
     
      o
     
     
      
       t
      
      
       1
      
     
     
      =
     
     
      (
     
     
      1
     
     
      ,
     
     
      3
     
     
      )
     
     
     
      d
     
     
      o
     
     
      
       t
      
      
       2
      
     
     
      =
     
     
      (
     
     
      5
     
     
      ,
     
     
      7
     
     
      )
     
     
     
      (
     
     
      n
     
     
      =
     
     
      2
     
     
      )
     
    
    
      dot_1 = (1,3)\\dot_2=(5,7)\\(n=2) 
    

    dot1​=(1,3)dot2​=(5,7)(n=2)

  2. 用两个变量空间x,y分别表示特征对应的向量 x = [ 1 5 ] , y = [ 3 7 ] x=\begin{bmatrix} 1\5 \end{bmatrix} , y=\begin{bmatrix} 3\7 \end{bmatrix} x=[15​],y=[37​]

  3. 计算特征的均值 x ‾ = 3 , y ‾ = 5 \overline{x}=3,\overline{y}=5 x=3,y​=5

  4. 计算协方差 C o v ( x , x ) = ( 1 − 3 ) 2 + ( 5 − 3 ) 2 2 − 1 = 8 C o v ( x , y ) = ( 1 − 3 ) ( 3 − 5 ) + ( 5 − 3 ) ( 7 − 5 ) 2 − 1 = 8 C o v ( y , x ) = C o v ( x , y ) = 8 C o v ( y , y ) = ( 3 − 5 ) 2 + ( 7 − 5 ) 2 2 − 1 = 8 Cov(x,x) = \frac{(1-3)^2+(5-3)^2}{2-1}=8\ Cov(x,y) = \frac{(1-3)(3-5)+(5-3)(7-5)}{2-1}=8\ Cov(y,x)=Cov(x,y)=8\ Cov(y,y) = \frac{(3-5)^2+(7-5)^2}{2-1}=8 Cov(x,x)=2−1(1−3)2+(5−3)2​=8Cov(x,y)=2−1(1−3)(3−5)+(5−3)(7−5)​=8Cov(y,x)=Cov(x,y)=8Cov(y,y)=2−1(3−5)2+(7−5)2​=8

  5. 生成协方差矩阵 C o v ( z ) = [ C o v ( x , x ) C o v ( x , y ) C o v ( y , x ) C o v ( y , y ) ] = [ 8 8 8 8 ] Cov(z)= \begin{bmatrix} Cov(x,x) & Cov(x,y)\ Cov(y,x) & Cov(y,y) \end{bmatrix} = \begin{bmatrix} 8 & 8\ 8 & 8 \end{bmatrix} Cov(z)=[Cov(x,x)Cov(y,x)​Cov(x,y)Cov(y,y)​]=[88​88​]

下面用代码实现上述过程:

import numpy as np
x = np.array([1,5])
y = np.array([3,7])
z = np.stack([x,y])# z=[[1,5],[3,7]]
result = np.cov(z)# 生成协方差矩阵
result的值
[[8.8.][8.8.]]

意义:协方差用来描述X和Y的相关程度
值范围意义Cov( X , Y ) < 0X与Y负相关Cov( X , Y ) > 0X与Y正相关Cov( X , Y ) = 0X与Y不相关

Sklearn线性模型

线性回归

给一些点

(xi,yi)

,用线性回归找出一条线

y=wx+b

,该线能够最大程度的与点拟合。

通过这条回归线,我们能根据

xi

预测出

yi

的大概值。代码实现如下:

# 核心代码
model = LinearRegression()# 定义线性模型
model.fit(x, y)# 根据(x,y)点集生成线性模型
x_test =[[4],[5],[6]]# 测试数据
y_test = model.predict(x_test)# 模型预测结果
# 完整代码import numpy as np
from sklearn.linear_model import LinearRegression

# 准备自变量与因变量# 这部分不用看,只知道生成了(x,y)散点即可
x = np.array([0,1,2,3,4])# 自变量x
y =3* x +2# 因变量y: [ 2  5  8 11 14]
x = x + np.random.rand(5)# 将点用随机数打乱
x =[[i]for i in x]# 行变列,如[1,2,3]会变成[[1],[2],[3]]
y =[[i]for i in y]# 行变列,这是sklearn包要求的格式# 建立线性模型
model = LinearRegression()# 定义线性模型
model.fit(x, y)# 根据(x,y)点集生成线性模型# 准备测试数据
x_test =[[4],[5],[6]]# 打印预测结果
y_test = model.predict(x_test)print(y_test)print("w值:", model.coef_)print("b截距值为:", model.intercept_)
# 输出[[12.79914287][15.74000827][18.68087368]]
w值:[[2.9408654]]
b截距值为:[1.03568125]

上述代码生成了以下线性模型

     y
    
    
     =
    
    
     w
    
    
     x
    
    
     +
    
    
     b
    
    
     =
    
    
     2.9408654
    
    
     x
    
    
     +
    
    
     1.03568125
    
   
   
     y=wx+b=2.9408654x+1.03568125 
   
  
 y=wx+b=2.9408654x+1.03568125

将测试数据x代入该公式即可得到预测值y。

后面的pytorch部分将会通过梯度下降的方法来生成线性模型。

逻辑回归

以鸢尾花数据集为例。与上述线性回归极其相似,因此不作过多解释。

# 完整代码from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 获取数据集
iris = datasets.load_iris()
iris_x = iris.data
iris_y = iris.target
# 留出法划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris_x, iris_y, test_size=0.1)# 生成逻辑回归模型
model = LogisticRegression()
model.fit(x_train, y_train)# 检验模型
y_pred = model.predict(x_test)
accu = accuracy_score(y_test, y_pred)

Pytorch简介

偏导数计算

计算

    y
   
   
    =
   
   
    (
   
   
    x
   
   
    +
   
   
    w
   
   
    )
   
   
    (
   
   
    w
   
   
    +
   
   
    1
   
   
    )
   
  
  
   y=(x+w)(w+1)
  
 
y=(x+w)(w+1)对

 
  
   
    x
   
  
  
   x
  
 
x的偏导数,公式可以分解为下图:

#mermaid-svg-hVivz7Xc8LqeDbUO {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .error-icon{fill:#552222;}#mermaid-svg-hVivz7Xc8LqeDbUO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hVivz7Xc8LqeDbUO .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-hVivz7Xc8LqeDbUO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hVivz7Xc8LqeDbUO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hVivz7Xc8LqeDbUO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hVivz7Xc8LqeDbUO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hVivz7Xc8LqeDbUO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hVivz7Xc8LqeDbUO .marker.cross{stroke:#333333;}#mermaid-svg-hVivz7Xc8LqeDbUO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hVivz7Xc8LqeDbUO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .cluster-label text{fill:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .cluster-label span{color:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .label text,#mermaid-svg-hVivz7Xc8LqeDbUO span{fill:#333;color:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .node rect,#mermaid-svg-hVivz7Xc8LqeDbUO .node circle,#mermaid-svg-hVivz7Xc8LqeDbUO .node ellipse,#mermaid-svg-hVivz7Xc8LqeDbUO .node polygon,#mermaid-svg-hVivz7Xc8LqeDbUO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hVivz7Xc8LqeDbUO .node .label{text-align:center;}#mermaid-svg-hVivz7Xc8LqeDbUO .node.clickable{cursor:pointer;}#mermaid-svg-hVivz7Xc8LqeDbUO .arrowheadPath{fill:#333333;}#mermaid-svg-hVivz7Xc8LqeDbUO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hVivz7Xc8LqeDbUO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hVivz7Xc8LqeDbUO .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-hVivz7Xc8LqeDbUO .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-hVivz7Xc8LqeDbUO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hVivz7Xc8LqeDbUO .cluster text{fill:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO .cluster span{color:#333;}#mermaid-svg-hVivz7Xc8LqeDbUO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hVivz7Xc8LqeDbUO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

      1
     

      y
     

      *
     

      a
     

      b
     

      +
     

      x
     

      w
     

      +
     

      w
     

用pytorch构建上述公式,可以很容易的求出偏导数,代码如下:

import torch

# 生成公式 y=(x+w)*(w+1)
x = torch.tensor([2.0], requires_grad=True)# 求x的偏导数,必须使requires_grad=True,否则报错
w = torch.tensor([1.0])
a = torch.add(x, w)# a = x+w
b = torch.add(w,1)# b = w+1
y = torch.mul(a, b)# y = a*b# 反向传播,计算所有requires_grad=True张量(tensor)的导数
y.backward()print(x.grad)# x的偏导数
# 结果
tensor([2.])

多次求导

backward(retain_graph=True)

可以保留计算图,再调用一次

backward()

即可实现二阶求导。代码修改如下:

# 核心代码
y.backward(retain_graph=True)# 计算保留图,用于二次求导print(x.grad)# x的一阶导
y.backward()# 二次求导print(x.grad)# x的二阶导
# 完整代码import torch

# 构建公式 y=(x+w)*(w+1)
x = torch.tensor([2.0], requires_grad=True)# 求x的偏导数,必须使requires_grad=True,否则报错
w = torch.tensor([1.0])
a = torch.add(x, w)# a = x+w
b = torch.add(w,1)# b = w+1
y = torch.mul(a, b)# y = a*b# 反向传播,计算所有requires_grad=True的导数
y.backward(retain_graph=True)# 计算保留图,用于二次求导print(x.grad)# x的一阶导
y.backward()print(x.grad)# x的二阶导

非标量输出

使用

torch.cat()

函数我们可以将不同的函数结合到一起,实现下图计算:

#mermaid-svg-eCsndn90A4qvwq96 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eCsndn90A4qvwq96 .error-icon{fill:#552222;}#mermaid-svg-eCsndn90A4qvwq96 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eCsndn90A4qvwq96 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-eCsndn90A4qvwq96 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eCsndn90A4qvwq96 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eCsndn90A4qvwq96 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eCsndn90A4qvwq96 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eCsndn90A4qvwq96 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eCsndn90A4qvwq96 .marker.cross{stroke:#333333;}#mermaid-svg-eCsndn90A4qvwq96 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eCsndn90A4qvwq96 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eCsndn90A4qvwq96 .cluster-label text{fill:#333;}#mermaid-svg-eCsndn90A4qvwq96 .cluster-label span{color:#333;}#mermaid-svg-eCsndn90A4qvwq96 .label text,#mermaid-svg-eCsndn90A4qvwq96 span{fill:#333;color:#333;}#mermaid-svg-eCsndn90A4qvwq96 .node rect,#mermaid-svg-eCsndn90A4qvwq96 .node circle,#mermaid-svg-eCsndn90A4qvwq96 .node ellipse,#mermaid-svg-eCsndn90A4qvwq96 .node polygon,#mermaid-svg-eCsndn90A4qvwq96 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eCsndn90A4qvwq96 .node .label{text-align:center;}#mermaid-svg-eCsndn90A4qvwq96 .node.clickable{cursor:pointer;}#mermaid-svg-eCsndn90A4qvwq96 .arrowheadPath{fill:#333333;}#mermaid-svg-eCsndn90A4qvwq96 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eCsndn90A4qvwq96 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eCsndn90A4qvwq96 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-eCsndn90A4qvwq96 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-eCsndn90A4qvwq96 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eCsndn90A4qvwq96 .cluster text{fill:#333;}#mermaid-svg-eCsndn90A4qvwq96 .cluster span{color:#333;}#mermaid-svg-eCsndn90A4qvwq96 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eCsndn90A4qvwq96 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

      y0=(x+w)(w+3)
     

      ∂(y0)/∂w = 7
     

      ∂loss/∂w = ∂(y0)/∂w * 1 + ∂(y1)/∂w * 2
     

      = 7 * 1 + 2 * 2 = 11
     

      y1=(x+w)+(w+3)
     

      ∂(y1)/∂w = 2
     

代码实现如下

# 核心代码
loss = torch.cat([y0, y1], dim=0)# dim=0代表横向拼接
loss_w = torch.tensor([1.,2.])# 设置权重,y0为1,y1为2
loss.backward(gradient=loss_w)# 反向传播
# 完整代码import torch
# 构建两个公式
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.],)
a = torch.add(w, x)
b = torch.add(w,3)
y0 = torch.mul(a, b)# y0 = (x+w)(w+3)
y1 = torch.add(a, b)# y1 = (x+w)+(w+3)# 合并公式
loss = torch.cat([y0, y1], dim=0)# dim=0代表横向拼接
loss_w = torch.tensor([1.,2.])# 设置权重,y0为1,y1为2
loss.backward(gradient=loss_w)# 反向传播print(w.grad)# w的偏导数
# 输出
tensor([11.])

线性回归

问题:给定若干

    (
   
   
    x
   
   
    ,
   
   
    y
   
   
    )
   
  
  
   (x,y)
  
 
(x,y)点集,找出一条直线

 
  
   
    y
   
   
    =
   
   
    w
   
   
    x
   
   
    +
   
   
    b
   
  
  
   y=wx+b
  
 
y=wx+b,使所有点到直线的距离之和最小。

目标:找到合适的

    w
   
  
  
   w
  
 
w与

 
  
   
    b
   
  
  
   b
  
 
b,使损失函数 

 
  
   
    L
   
   
    =
   
   
    
     1
    
    
     N
    
   
   
    
     ∑
    
    
     
      i
     
     
      =
     
     
      1
     
    
    
     N
    
   
   
    (
   
   
    w
   
   
    
     x
    
    
     i
    
   
   
    +
   
   
    b
   
   
    −
   
   
    
     y
    
    
     
      t
     
     
      r
     
     
      u
     
     
      e
     
    
   
   
    
     )
    
    
     2
    
   
  
  
   L=\frac{1}{N}\sum_{i=1}^{N}(wx_i+b-y_{true})^2
  
 
L=N1​∑i=1N​(wxi​+b−ytrue​)2 的值最小。

方法:我们需要对损失函数关于

    w
   
  
  
   w
  
 
w和

 
  
   
    b
   
  
  
   b
  
 
b求导:

 
  
   
    
     
      ∂
     
     
      L
     
    
    
     
      ∂
     
     
      w
     
    
   
  
  
   \frac{\partial{L}}{\partial{w}}
  
 
∂w∂L​,

 
  
   
    
     
      ∂
     
     
      L
     
    
    
     
      ∂
     
     
      b
     
    
   
  
  
   \frac{\partial{L}}{\partial{b}}
  
 
∂b∂L​,然后使用公式

 
  
   
    
     
      w
     
     
      
       t
      
      
       +
      
      
       1
      
     
    
    
     =
    
    
     
      w
     
     
      t
     
    
    
     −
    
    
     μ
    
    
     
      
       ∂
      
      
       L
      
     
     
      
       ∂
      
      
       w
      
     
    
    
    
     
      b
     
     
      
       t
      
      
       +
      
      
       1
      
     
    
    
     =
    
    
     
      b
     
     
      t
     
    
    
     −
    
    
     μ
    
    
     
      
       ∂
      
      
       L
      
     
     
      
       ∂
      
      
       b
      
     
    
    
    
     (
    
    
     μ
    
    
     :
    
    
     学
    
    
     习
    
    
     率
    
    
     ,
    
    
     梯
    
    
     度
    
    
     下
    
    
     降
    
    
     的
    
    
     跨
    
    
     度
    
    
     )
    
   
   
     w_{t+1}=w_t-\mu\frac{\partial{L}}{\partial{w}} \\ b_{t+1}=b_t-\mu\frac{\partial{L}}{\partial{b}} \\(\mu:学习率,梯度下降的跨度) 
   
  
 wt+1​=wt​−μ∂w∂L​bt+1​=bt​−μ∂b∂L​(μ:学习率,梯度下降的跨度)

不断调整

    w
   
  
  
   w
  
 
w与

 
  
   
    b
   
  
  
   b
  
 
b的值,直到得到合适的线性模型。
import matplotlib.pyplot as plt
import torch

# 准备自变量与因变量# 这部分不用看,只知道生成了(x,y)散点即可
x = torch.rand(20,1)*10# [20*1]的0-1的随机数 * 10
y =2* x +(5+ torch.randn(20,1))# y = 2x + 5# 学习率
mu =0.05# 构建线性回归参数 y_pred = wx + b
w = torch.tensor(5.0, requires_grad=True)# 初始化w
b = torch.tensor(10.0, requires_grad=True)# 初始化b# 迭代训练1000次for i inrange(1000):"""向前传播,计算预测值 y_pred = wx + b"""
    wx = torch.mul(w, x)# wx = w * x
    y_pred = torch.add(wx, b)# y_pred = w * x + b# 计算MSE loss# 目的是为了使loss尽可能小
    loss =(0.5*(y - y_pred)**2).mean()# 反向传播,求b与w的偏导数
    loss.backward()# 更新参数# 此处等同于 w = w.sub(w,lr*w.grad)# 后面带下划线的都是in-place的,会将调用者改变
    w.data.sub_(mu * w.grad)# 调整w的值
    b.data.sub_(mu * b.grad)# 调整b的值# 更新参数后一定要清零梯度if i !=999:
        w.grad.zero_()
        b.grad.zero_()# 每隔50次循环输出一次图像if i %50==0:
        plt.scatter(x.data.numpy(), y.data.numpy())# 散点
        plt.plot(x.data.numpy(), y_pred.data.numpy())# 回归直线
        plt.show()

SVM


本文转载自: https://blog.csdn.net/qq_15989473/article/details/125133281
版权归原作者 阿腾木 所有, 如有侵权,请联系我们删除。

“机器学习基础备忘录”的评论:

还没有评论