-
1+1等于几 ?
-
50- 傻x,多了
-
1+2等于几?
-
20- 傻x,多了
-
3+4等于几
-
7
-
傻x,对了
-
6+9等于几
-
13
-
傻x,少了
很多很多次以后……
-
2+2等于几
-
4
-
4+5等于几
-
9
这就是机器学习,准确来说是最常见的一种,监督学习。最开始的几步是对于模型的训练,“多了”或“少了”可以理解为训练时的误差,模型根据误差调整自身参数,这就是机器学习里常用的反向传播(Backpropagation)的简单的解释。梯度下降涉及到计算,真没想到该怎么通俗解释。
拟合函数关系
话归前文,KNN算法的问题,有问题我们才需要优化,才需要其他的解决方案
- KNN算法比较低效,其需要加载所有的数据,当数据比较大的时候,我们需要加载,而这个时候算法的低效就有了瓶颈(内存要求较高、预测阶段可能很慢)
- 对不相关的功能和数据规模敏感,如果数据中有太多的不相关数据,那么对于预测就有非常大的干预,造成预测误判。
所以我们如果能够找到X_rm和Y质检的函数关系,那么我们每次要计算的时候,输入这个函数,那么我们就能很快的预测值,那么这种方式我们称呼为:拟合函数关系
如果我们现在假设上图中的函数关系为:
f(x)=k*x+b
那么如果我们将函数拟合的非常的好,那么我们预测一个值的时候我们只需要带入x便可以求出f(x),只是将问题转化为单纯的数学问题(当然这个是最难的,但是现在由于有了深度学习,可以做到动态拟合,且听博主娓娓道来)。
1.1 先说好,我们先说坏
观察上图,我们发现其k,b可能会有多个值,甚至有多段函数,乃至多个维度,那么我们预测出来的值的正确率用什么来评估呢?
损失函数 Loss函数
我们本个系列中使用的Loss函数的数学基础使用的就是下文:
https://zhuanlan.zhihu.com/p/58883095
l o s s ( y , y ^ ) = 1 N ∑ i ∈ N ( y i − y i ^ ) 2 loss(y,\hat{y})=\frac{1}{N}{\sum_{i \in N}(y_i-\hat{y_i})^2} loss(y,y^)=N1i∈N∑(yi−yi^)2
如果我们预测了多组k、b那么将X_rm,以及k、b带入到函数中,如果一组k、b求出来的值最小那么我们就认为求出来的k、b是最优的。
那么我们给上述的方法取一个非常nb的名字:最小二乘法(实质上为:Mean Squared Error:MSE)
关于最小二乘法的介绍我就给一下链接,就不再这里展开了。(以下三篇博文建议依次阅读)
https://matongxue.blog.csdn.net/article/details/81127117?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
https://www.cnblogs.com/paiandlu/p/7843236.html
https://www.bilibili.com/read/cv4143589/
real_y=[3,6,7]
y_hats=[3,4,7]
y_hats_2=[3,6,6]
def loss(y,yhat):
return np.mean((np.array(y)-np.array(yhat))**2)
print(loss(real_y,y_hats))
print(loss(real_y,y_hats_2))
1.2 如何计算k、b
1.2.1 我们使用微积分的方法做计算,接上文
https://www.cnblogs.com/paiandlu/p/7843236.html
中的计算思路
但是一般不适用微积分+最小二乘法来计算,原因如下:
https://www.zhihu.com/question/23817253/answer/85072173
1.2.2 使用随机模拟的方式来计算 StochasticSimulation
import random
def model(x,k,b):
return x*k+b
def StochasticSimulation(X_rm,total_times=1000):
Var_Max,Var_Min=100,-100
min_loss=float('inf')
best_k,best_b=None,None
for t in range(total_times):
k,b=random.randint(Var_Min,Var_Max),random.randint(Var_Min,Var_Max)
loss_=loss(Y,model(X_rm,k,b))
if loss_<min_loss:
min_loss=loss_
best_k,best_b=k,b
print('在{}时刻我找到更好的k:{}和b:{},这个时候的loss是:{}'.format(t,k,b,loss_))
StochasticSimulation(X_rm)
StochasticSimulation(X_rm,10000)
1.2.3 梯度下降GradientDescent
k n + 1 = k n + − 1 ∗ ∂ l o s s ( k , b ) ∂ k n k_{n+1} =k_{n} + -1 * \frac{\partial{loss(k,b)}}{\partial{k_{n}}} kn+1=kn+−1∗∂kn∂loss(k,b)
b n + 1 = b n + − 1 ∗ ∂ l o s s ( b , b ) ∂ b n b_{n+1} =b_{n} + -1 * \frac{\partial{loss(b,b)}}{\partial{b_{n}}} bn+1=bn+−1∗∂bn∂loss(b,b)
def loss(y,yhat):
return np.mean((np.array(y)-np.array(yhat))**2)
def partial_k(x,y,k,b):
return 2 * np.mean((y - (k * x + b))*(-x))
def partial_b(x,y,k,b):
return 2 * np.mean((y - (k * x + b))*(-1))
def GradientDescent(x,y,total_times=1000):
k,b=random.random(),random.random()
min_loss=float('inf')
best_k,best_b=k,b
alphatest=1e-3
for t in range(total_times):
k=k+(-1)* partial_k(x,y,k,b) * alphatest
b=b+(-1) * partial_b(x,y,k,b) * alphatest
loss_=loss(y,model(x,k,b))
#print('在{}时刻我找到更好的k:{}和b:{},这个时候的loss是:{}'.format(t,k,b,loss_))
if loss_<min_loss:
min_loss=loss_
best_k,best_b=k,b
print('在{}时刻我找到更好的k:{}和b:{},这个时候的loss是:{}'.format(t,k,b,loss_))
return best_k,best_b
GradientDescent(X_rm,Y,10)
GradientDescent(X_rm,Y,20)
上述的算法就是梯度下降算法,相较于随机模拟,每一次模拟相较之前的模拟都会优化,但是随机模拟就有很大的随机性。
plt.scatter(X_rm,Y)
best_k,best_b=GradientDescent(X_rm,Y,1000)
print('{}:{}'.format(best_k,best_b))
plt.plot(X_rm,best_k*X_rm+best_b)
best_k,best_b=GradientDescent(X_rm,Y,20000)
print('{}:{}'.format(best_k,best_b))
plt.plot(X_rm,best_k*X_rm+best_b)
best_k,best_b=GradientDescent(X_rm,Y,30000)
print('{}:{}'.format(best_k,best_b))
plt.plot(X_rm,best_k*X_rm+best_b)
对比knn和梯度下降
- 预测值上,我们预测7和4
find_price_by_similar(rm_to_price,7)
model(7,best_k,best_b)
find_price_by_similar(rm_to_price,4)
model(4,best_k,best_b)
- 发现1: 相对参考分布图,7的值预测的差不多,而4的值knn预测的偏离预期较大
%%time
find_price_by_similar(rm_to_price,4)
%%time
model(4,best_k,best_b)
- 发现2: knn预测时间明显低于拟合函数