对数值类数据建模—加权k近邻算法
根据相邻的数据预测出目标的取值情况
算法:
- 计算给定向量与所有其他数据的距离,并按照距离排序
- 选出前k位,求前k个数据的加权平均,权重根据距离求得
要点:
- 计算距离:使用欧几里得距离算法
- 计算权重算法:
- 反函数
- 减法函数
- 高斯函数
- 缩放:对于各个变量的取值范围相差较大的情况或者属性对结果的影响程度不同的情况可以进行缩放,通过优化算法找到合适缩放参数
- 交叉验证:用来评估算法预测的准确性。将给定数据集分成训练集、测试集,先使用训练集训练算法,然后使用算法计算测试集中数据,将结果和测试数据集对比,计算出误差
- 估计概率密度:给出预测值范围,对于同一情况的取值不确定(可能有其他因素影响,但是没有反映出来,比如同一瓶葡萄酒有的是原价,有的是打折的,打折这个因素并没有考虑在内),这个时候可以给出一个预测值的范围,而不是一个简单的数字
优点:
- 无任何计算开销的情况下加入新的测试数据(因为算法使用的是加权值计算的)
缺点:
- 预测的计算量较大,因为要计算每个点到其他所有点的距离
- 在变量较多(但是各个变量对结果的影响程度是不一样的)的情况下,很难确定合理的权重值,可以通过“优化”解决这个问题
适用场景:
对包含多种数值型属性进行预测
from random import random, randint
import math
def wineprice(rating, age):
"""
根据等级和年份计算红酒的价格
Args:
rating:红酒等级
age:红酒年份
Returns:
返回红酒的价格
"""
peak_age = rating - 50
# 根据等级计算价格
price = rating / 2
if age > peak_age:
# 经过峰值年之后,后继5年里品质将会变差
price = price * (5 - (age - peak_age))
else:
# 在接近峰值年的时候,价格会增加到原来的5倍
price = price * (5 * ((age + 1) / peak_age))
if price < 0:
price = 0
return price
def wineset1():
"""
构造红酒价格数据集
"""
rows = []
for i in range(300):
# 随机生成年代和等级
rating = random() * 50 + 50
age = random() * 50
# 得到一个参考价格
price = wineprice(rating, age)
# 增加噪声
price = price * (random() * 0.4 + 0.8)
# 加入数据集
rows.append({
'input':(rating, age), 'result':price})
return rows
def euclidean(v1, v2):
"""
利用欧几里得距离算法计算相似度
Args:
v1:需要计算相似度的数据
v2:需要计算相似度的数据
"""
d = 0.0
for i in range(len(v1)):
d += (v1[i] - v2[i]) ** 2
return math.sqrt(d)
def getdistance(data, vec1):
"""
计算按照与给定数据vec1的距离的大小排序的数据集合
Args:
data:数据集合
vec1:需要计算的数据
Returns:
返回按照距离排序后的数据集合
"""
distancelist = []
for i in range(len(data)):
vec2 = data[i]['input']
# 记录vec1与对应数据的相似度和该数据的index
distancelist.append((euclidean(vec1, vec2), i))
# 按照距离进行排序
distancelist.sort()
return distancelist
# KNN 最近邻算法
def knnestimate(data, vec1, k=5):
"""
计算前k项的平均值
Args:
data:数据集
vec1:给定向量