K近邻算法实战

K近邻算法实战

解决问题:将房屋属性输入,根据历史房屋数据,给出房屋价格。

K近邻算法概述

数据读取
import pandas as pd
#保留原始数据中的这些特征,截取部分特征使用
features = ['accommodates','bedrooms','bathrooms','beds','price','minimum_nights','maximum_nights','number_of_reviews']

dc_listings = pd.read_csv('listings.csv')
#指定特征
dc_listings = dc_listings[features]

print(dc_listings.shape)

dc_listings.head()

price就当作标签。
在这里插入图片描述

K近邻

在这里插入图片描述

K近邻原理

在这里插入图片描述
这里的相似程度就是房间数差异,因为想要找1一间房的,所以与一间房的差异都是0.
在这里插入图片描述
对这三个价格做了平均得到105。
在这里插入图片描述

距离的定义

欧式距离公式(每一个特征的差异):
其中Q1到Qn是一条数据的所有特征信息,P1到Pn是另一条数据的所有特征信息。
在这里插入图片描述
假设我们要估价的房子有三个房间。

import numpy as np

our_acc_value = 3
#用当前每条数据的房间数减去3,得到历史数据里的房子与我们房子的差异。(绝对值计算)
dc_listings['distance'] = np.abs(dc_listings.accommodates - our_acc_value)
dc_listings.distance.value_counts().sort_index()

值为0的就是跟我们房间数一样的房子。
在这里插入图片描述
因为有可能数据是按照某些顺序排列的,所以进行打乱。
sample操作可以得到洗牌后的数据

dc_listings = dc_listings.sample(frac=1,random_state=0)
dc_listings = dc_listings.sort_values('distance')
dc_listings.price.head()

在这里插入图片描述
因为价格是字符串类型,所以需要转换一下。

dc_listings['price'] = dc_listings.price.str.replace("\$|,",'').astype(float)

mean_price = dc_listings.price.iloc[:5].mean()
mean_price

得到平均价格就是我们房子的大致价格了。
在这里插入图片描述

模型评估

因为无法得知我们预测的结果是否准确,所以要对模型进行评估。

切分数据集

划分数据集:因为训练集经过训练了,再使用训练集测试,会过拟合,结果不科学,所以留一部分没用过的数据进行测试。
在这里插入图片描述

dc_listings.drop('distance',axis=1)

train_df = dc_listings.copy().iloc[:2792]
test_df = dc_listings.copy().iloc[2792:]
基于单变量预测价格
def predict_price(new_listing_value,feature_column):
    temp_df = train_df
    #算相似度
    temp_df['distance'] = np.abs(dc_listings[feature_column] - new_listing_value)
    #相似度排序选前五个
    temp_df = temp_df.sort_values('distance')
    knn_5 = temp_df.price.iloc[:5]
    #算均值
    predicted_price = knn_5.mean()
    #得到房价
    return(predicted_price)

再dataframe使用apply相当于对每一个样本执行同一个操作。得到预测结果。

test_df.accommodates.apply(predict_price,feature_column='accommodates')
进行评估

公式如下。
在这里插入图片描述
公式代码实现:

#差值平方
test_df['squared_error'] = (test_df['predicted_price'] - test_df['price'])**(2)
#均值
mse = test_df['squared_error'].mean()
#开根号
rmse = mse ** (1/2)
rmse

希望此值越小越好
在这里插入图片描述

使用不同变量作为特征

遍历每一个选出来的特征,分别求价格和模型评估

for feature in ['accommodates','bedrooms','bathrooms','number_of_reviews']:
    #test_df['predicted_price'] = test_df.accommodates.apply(predict_price,feature_column=feature)
    test_df['predicted_price'] = test_df[feature].apply(predict_price,feature_column=feature)
    test_df['squared_error'] = (test_df['predicted_price'] - test_df['price'])**(2)
    mse = test_df['squared_error'].mean()
    rmse = mse ** (1/2)
    print("RMSE for the {} column: {}".format(feature,rmse))

在这里插入图片描述
这边有一个问题需要考虑。当我们用欧式距离计算的时候,比如A这个特征,他的取值范围比较大,那么在求误差时,就会比较大;B这个特征,他的取值范围比较小,求误差时,就会相对较小。所以下面进行数据预处理。
在这里插入图片描述
数据标准化与归一化。
在这里插入图片描述
在这里插入图片描述

import pandas as pd
from sklearn.preprocessing import StandardScaler
features = ['accommodates','bedrooms','bathrooms','beds','price','minimum_nights','maximum_nights','number_of_reviews']

dc_listings = pd.read_csv('listings.csv')

dc_listings = dc_listings[features]
#家隔类型转换
dc_listings['price'] = dc_listings.price.str.replace("\$|,",'').astype(float)
#缺失值
dc_listings = dc_listings.dropna()
#标准化
dc_listings[features] = StandardScaler().fit_transform(dc_listings[features])

normalized_listings = dc_listings

print(dc_listings.shape)

normalized_listings.head()

在这里插入图片描述
划分数据集。

norm_train_df = normalized_listings.copy().iloc[0:2792]
norm_test_df = normalized_listings.copy().iloc[2792:]

计算欧式距离。多个属性差值平方和开根号。
在这里插入图片描述
使用scipy中的包直接计算欧式距离

from scipy.spatial import distance

first_listing = normalized_listings.iloc[0][['accommodates', 'bathrooms']]
fifth_listing = normalized_listings.iloc[20][['accommodates', 'bathrooms']]
#调用distance的euclidean计算欧式距离,传入两个样本
first_fifth_distance = distance.euclidean(first_listing, fifth_listing)
first_fifth_distance

多变量KNN模型

def predict_price_multivariate(new_listing_value,feature_columns):
    #训练集
    temp_df = norm_train_df
    #计算有多个特征的样本之间的欧式距离
    temp_df['distance'] = distance.cdist(temp_df[feature_columns],[new_listing_value[feature_columns]])
    #保存距离
    temp_df = temp_df.sort_values('distance')
    #取出前五
    knn_5 = temp_df.price.iloc[:5]
    #求和,均值
    predicted_price = knn_5.mean()
    return(predicted_price)
#评估模型,使用之前说到的公式
cols = ['accommodates', 'bathrooms']
norm_test_df['predicted_price'] = norm_test_df[cols].apply(predict_price_multivariate,feature_columns=cols,axis=1)    
norm_test_df['squared_error'] = (norm_test_df['predicted_price'] - norm_test_df['price'])**(2)
mse = norm_test_df['squared_error'].mean()
rmse = mse ** (1/2)
print(rmse)

对数据进行预处理后,效果大大改善。
在这里插入图片描述

使用Sklearn 来完成KNN

导入模型

from sklearn.neighbors import KNeighborsRegressor
cols = ['accommodates','bedrooms']
#实例化模型,可以传入参数,K值,默认n_neighbors=5,就是取相似度排名的前五个,参数对结果有影响,可以自己调整。
knn = KNeighborsRegressor()
#训练 传入训练集X,Y
knn.fit(norm_train_df[cols], norm_train_df['price'])
#预测,使用测试集预测
two_features_predictions = knn.predict(norm_test_df[cols])

评估模型

from sklearn.metrics import mean_squared_error

two_features_mse = mean_squared_error(norm_test_df['price'], two_features_predictions)
two_features_rmse = two_features_mse ** (1/2)
print(two_features_rmse)

在这里插入图片描述

加入更多特征,参数不变,特征变多了,模型变好了。

knn = KNeighborsRegressor()

cols = ['accommodates','bedrooms','bathrooms','beds','minimum_nights','maximum_nights','number_of_reviews']

knn.fit(norm_train_df[cols], norm_train_df['price'])
four_features_predictions = knn.predict(norm_test_df[cols])
four_features_mse = mean_squared_error(norm_test_df['price'], four_features_predictions)
four_features_rmse = four_features_mse ** (1/2)
four_features_rmse

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值