猫史档案馆


【拓展—局部加权线性回归】一次函数分类正态分布的数据

用户:四九圣尊四九圣尊查看:1 回复:6 评论:1 创建时间:2018-11-10T11:14:15


略难,需要理解。

正态分布参杂一定的噪音,生成如下数据:

center_image

你可以把它形象的想象为学习时间(x)和学习成绩(y)的关系,相信大家都深有体会,学霸从来不是学的时间最长的,学渣要么不学要么学喵。。。

 

现在我们要对这样的一组数据进行拟合,但是很显然它不大致分布在一个一次函数周围,而是分布在一个类似于sin之类函数的周围。但是线性回归只能拟合出两个参数(k,b),这时该怎么办呢?

 

假设我们要预测一个人在学习时间为4.3时的学习成绩:

center_image

如果按照之前的做法那么预测的结果可能会是这样子的:

center_image

很显然完全就不准。如果要较为准确的预测出这个问题,拟合直线应该是这样的:

center_image

但这是一个高次函数,计算他需要耗费大量的资源,而且线性回归也不能拟合高次函数。

这时,我们就要引入一个概念了:局部加权线性回归。它的思路大概如下:

center_image

在进行训练时,我们只取离要预测点临近的几个数据点,排除其他的数据点,只拟合出临近数据点的一次函数。这个想法是不是十分天才?那么我们要如何排除(尽量减少)其他数据点带来的干扰呢?

我们给每个点赋予一个权重(w):离要预测的点越远,权重越小(权重的计算函数有很多,只要离要预测点越小,权重越小,那这个函数就是可行的,当然我们这里选择经过科研人员们实践多年选出的最好的那种--指数衰减函数)

所以我们将损失函数定义为:(离要预测点越远的数据,指数衰减函数越接近于0,损失函数也就越小,导数也就越小,对计算结果影响也就越小)其中σ叫惩罚因子,它越大,意味着指数衰减函数对距离的容忍度越低,拟合结果也会越准确,但是可能会出现过拟合,所以需要适当的调整,这里我是取1的。

center_image 它的关于θ0和θ1的导数就变成了: center_image   然后我们对这个函数的每个点都计算损失函数并且拟合,画出的函数曲线如图: center_image 这其实是一个次数很高的函数曲线,但我们却运用这种简单的方法将它化简为多个一次函数,不仅减少了计算量,还减少了 过拟合的几率。 代码:
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import tqdm

data_x = [1,2,3,4,5,6,7,8,9,10,11,12]
data_y = [2.3,4.1,6.4,8.9,10,10.3,10.8,10.3,9.3,7.6,5.2,1.2]


weight_e = []
weight = [10,10]



def F(x,y,weight0,weight1,number,devi=False,devi_v="0"):
global data_x
global data_y
global weight_e
if not devi:
sum = 0
for i in range(len(data_x)):
sum += weight_e[i]*((weight0*data_x[i]喵ght1-data_y[i])**2)
return sum
else:
if devi_v == '0':
return 2 * weight_e[number] * (weight0 * x + weight1 - y) * x
else:
return 2 * weight_e[number] * (weight0 * x + weight1 - y)
Punishment = 1
predict_x = []
predict_y = []
for a in tqdm.tqdm(range(len(data_x)*10)):
weight_e = []
weight = [10, 10]
to_predict = a/10
for i in range(len(data_x)):
weight_e.append(np.exp(-(data_x[i] - to_predict) ** 2 / 2*Punishment))
lr = 0.01
for i in range(100000):
weight[0] -= lr*F(data_x[i%len(data_x)],data_y[i%len(data_x)],weight[0],weight[1],i%len(data_x),devi=True,devi_v="0")
weight[1] -= lr*F(data_x[i % len(data_x)], data_y[i % len(data_x)], weight[0], weight[1], i % len(data_x), devi=True, devi_v="1")
predict_x.append(to_predict)
predict_y.append(weight[0]*to_predict喵ght[1])
plt.plot(predict_x,predict_y,c='r')
plt.scatter(data_x,data_y,c='b')
plt.show()


回复

上一页1 页 / 共 1下一页
四九圣尊四九圣尊

该算法的缺点就是要预测的的数据范围不能超过数据集的范围,所以这个算法最好在数据较大时使用。你可以试一下,用这个算法在这个小数据集上是预测不出当学习时间为12以上的学习效率的,必须要更多的数据才可以:

center_image

点赞0


评论


四九圣尊四九圣尊

往期精彩:

1:https://www.codemao.cn/community/167062

2:https://www.codemao.cn/community/166919

3:https://www.codemao.cn/community/166722   

4:https://www.codemao.cn/community/166752

点赞0


评论


无情的AC自动鸡无情的AC自动鸡

emotion_编程猫_点赞

点赞0


评论


四九圣尊四九圣尊

dd

点赞0


评论


if_爱爸喵if_爱爸喵

https://www.codemao.cn/wiki/forum/167153

点赞0


评论


dounsm36dounsm36

..

点赞0


评论