# 机器学习基础备忘录

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

## 距离计算

:

d

(

x

,

y

)

=

k

=

1

N

(

x

k

y

k

)

2

:d(x,y)=k=1N(xkyk)2

:

d

(

x

,

y

)

=

k

=

1

N

x

k

y

k

:d(x,y)=k=1Nxkyk

:

d

(

x

,

y

)

=

max

(

x

k

y

k

)

:d(x,y)=max(xkyk)

:

c

o

s

θ

=

x

1

x

2

+

y

1

y

2

x

1

2

+

x

2

2

y

1

2

+

y

2

2

:cosθ=x12+x22

y12+y22

x1x2+y1y2

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)



### 交叉验证法

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



# 核心代码
"""

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])

# 输出
————————————————————————————————

————————————————————————————————

————————————————————————————————



### 留一法

# 核心代码
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])

# 输出
————————————————————————————————

————————————————————————————————

————————————————————————————————

————————————————————————————————



## 性能度量

### 均方误差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=n1i=1n(f(xi)yi)2

# 核心代码
"""

"""
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=n1i=1n(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=n1i=1mf(xi)yi

# 实现
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=n1i=1n(f(xi)=yi)

# 核心代码
"""

"""
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)


### 混淆矩阵

• 查准率：预测为正中，预测正确的概率

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

# 核心代码
"""

"""
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])

# 输出
[[0 1]
[2 1]]


0 0 1
1 2 1

0 0 0 真正例TP = 0
0 1 1 假反例FN = 1，预测错误1次
1 0 2 假正例FP = 2，预测错误2次
1 1 1 真反例TN = 1，预测成功1次

=

T

P

T

P

+

F

P

=

0

0

+

2

=

0

=TP+FPTP=0+20=0

=

T

P

T

P

+

F

N

=

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

=TP+FP+TN+FNTP+TN=0+2+1+10+1=41

# 查准率
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曲线

R

O

C

X

f

p

r

=

F

P

F

P

+

T

N

=

ROC曲线X轴：fpr=frac{FP}{FP+TN}=frac{真实情况中：反例预测错误的}{真实情况中：反例总和}

ROC线Xfpr=FP+TNFP=

R

O

C

Y

t

p

r

(

)

=

T

P

T

P

+

F

N

=

ROC曲线Y轴：tpr(查全率)=frac{TP}{TP+FN}=frac{真实情况中：正例中预测正确的}{真实情况中：正例总和}

ROC线Ytpr()=TP+FNTP=

# 核心代码
"""
x轴列表, y轴列表, _ = roc_curve(真实数据,预测数据)

"""
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)=n1i=1n(xix)(yiy)

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)

1. 用两个变量空间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]

2. 计算特征的均值

x

=

3

,

y

=

5

overline{x}=3,overline{y}=5

x=3,y=5

3. 计算协方差

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)=21(13)2+(53)2=8Cov(x,y)=21(13)(35)+(53)(75)=8Cov(y,x)=Cov(x,y)=8Cov(y,y)=21(35)2+(75)2=8

4. 生成协方差矩阵

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)]=[8888]

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.]]


Cov( X , Y ) < 0 X与Y负相关
Cov( X , Y ) > 0 X与Y正相关
Cov( X , Y ) = 0 X与Y不相关

## Sklearn线性模型

### 线性回归

# 核心代码
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

### 逻辑回归

# 完整代码
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_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

import torch

# 生成公式 y=(x+w)*(w+1)
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
y.backward()

# 结果
tensor([2.])


### 多次求导

backward(retain_graph=True)可以保留计算图，再调用一次backward()即可实现二阶求导。代码修改如下：

# 核心代码
y.backward(retain_graph=True)  # 计算保留图，用于二次求导
y.backward()  # 二次求导

# 完整代码
import torch

# 构建公式 y=(x+w)*(w+1)
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
y.backward(retain_graph=True)  # 计算保留图，用于二次求导
y.backward()


### 非标量输出

#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

# 完整代码
import torch
# 构建两个公式
x = torch.tensor([2.], )
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

# 输出
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=N1i=1N(wxi+bytrue)2 的值最小。

w

w

w

b

b

b求导:

L

w

frac{partial{L}}{partial{w}}

wL,

L

b

frac{partial{L}}{partial{b}}

bL,然后使用公式

w

t

+

1

=

w

t

μ

L

w

b

t

+

1

=

b

t

μ

L

b

(

μ

:

)

w_{t+1}=w_t-mufrac{partial{L}}{partial{w}} \ b_{t+1}=b_t-mufrac{partial{L}}{partial{b}} \(mu:学习率，梯度下降的跨度)

wt+1=wtμwLbt+1=btμbL(μ:)

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 in range(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()
# 更新参数
# 后面带下划线的都是in-place的,会将调用者改变
# 更新参数后一定要清零梯度
if i != 999:
# 每隔50次循环输出一次图像
if i % 50 == 0:
plt.scatter(x.data.numpy(), y.data.numpy())  # 散点
plt.plot(x.data.numpy(), y_pred.data.numpy())  # 回归直线
plt.show()


THE END

)">