目录
一、K近邻算法概述
1、Airbnb 房价预测任务
数据读取
数据特征
2、K近邻原理
3、距离的定义(欧氏距离)
4、实例
二、模型的评估
1、首先制定好训练集和测试集
2、基于单变量预测价格
3、进行衡量
三、数据预处理
特征数据预处理——标准化与归一化
标准化
归一化
四、sklearn库与功能
五、多变量KNN模型
1、多变量距离的计算
2、多变量KNN模型
3、使用Sklearn来完成KNN
4、加入更多的特征
分类/回归问题都可以用该算法解决
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()
如果我有一个1个房间的房子,我能租多少钱呢???再综合考虑这三个就得到了我的房子大概能值多钱!
需要去看看1个房间的别人都租到多少钱!
K代表候选对象个数,也就是找和房间数量最相近的其他房子的价格
假设我们的数据源中只有5条信息,现在想针对我的房子(只有一个房间)来定一个价格。
在这里假设我们选择的K=3,也就是选3个跟我最相近的房源。
综合考虑这三个,得到了我的房子大概能值多钱!
如何才能知道哪些数据样本跟我最相近呢?
其中Q1到Qn是一条数据的所有特征信息,P1到Pn是另一条数据的所有特征信息
1、假设我们的房子有3个房间
import numpy as np our_acc_value = 3 dc_listings['distance'] = np.abs(dc_listings.accommodates - our_acc_value) dc_listings.distance.value_counts().sort_index()
2、这里我们只用了绝对值来计算,和我们距离为0的(同样数量的房间)有461个
3、 洗牌(打乱顺序),得到洗牌后的数据
dc_listings = dc_listings.sample(frac=1,random_state=0) dc_listings = dc_listings.sort_values('distance') dc_listings.price.head()
4、问题:这里面的数据是字符串,需要转换一下!
dc_listings['price'] = dc_listings.price.str.replace("\$|,",'').astype(float) mean_price = dc_listings.price.iloc[:5].mean() mean_price
5、得到了平均价格,也就是我们的房子大致的价格了 。
判断预测的值准不准!
将数据集进行切分,分成一个训练集(训练)和测试集(衡量效果)。
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)
test_df['predicted_price'] = test_df.accommodates.apply(predict_price,feature_column='accommodates')
这样我们就得到了测试集中,所有房子的价格了。
计算root mean squared error (RMSE)均方根误差
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))
看起来结果差异挺大,接下来综合利用所有的信息来一起进行测试 。
当用欧氏距离进行评估时,有些特征数据取值较大,有些特征数据取值较小。
由于特征值不同,导致在数值上有较大和较小的差异。需要对数据进行预处理。
对原始数据进行处理,进行standardization(或者叫做Z-score normalization)
要求:均值和标准差
转换公式如下:
意义:如果特征值之间的数值差异太大,那么更新的结果肯定会产生较大的差异。在最开始的时候,我们认为特征之间的重要程度是一样的,因此预处理的工作必须做!!
参数更新:
Min-Max scalling(或者叫“normalization”,也就是我们常说的0-1归一化)
处理后的所有特征的值都会被压缩到0到1区间上,这样做还可以抑制离群值对结果的影响。
归一化的公式:
python中使用最多的一个机器学习库。
(模块:分类、回归、距离、降维、模型选择、数据预处理)
API文档:API Reference — scikit-learn 1.0.2 documentation
学习案例:Examples — scikit-learn 1.0.2 documentation
标准化和归一化后数据分布不会发生变化,取值范围会发生改变
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()
排除了大的数值和小的数值之间从差异。
scipy中已经有现成的距离的计算工具了
from scipy.spatial import distance first_listing = normalized_listings.iloc[0][['accommodates', 'bathrooms']] fifth_listing = normalized_listings.iloc[20][['accommodates', 'bathrooms']] first_fifth_distance = distance.euclidean(first_listing, fifth_listing) first_fifth_distance
1、导入需要使用的模块;对KNN模型进行实例化;.fit:进行模型的训练;预测测试集之后的结果。
from sklearn.neighbors import KNeighborsRegressor cols = ['accommodates','bedrooms'] knn = KNeighborsRegressor(n_neighbors=20) knn.fit(norm_train_df[cols], norm_train_df['price']) two_features_predictions = knn.predict(norm_test_df[cols])
2、 计算RMSE结果 0.813735533525
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
K近邻不适用数据量大时。