Py学习  »  Python

用Python预测Airbnb 价格

Python程序员 • 4 年前 • 331 次点击  

机器学习无疑是目前数据科学中最热门的话题。它也是支撑一些最令人兴奋的技术领域的基本概念,比如自动驾驶汽车和预测分析。谷歌上机器学习的搜索量在2019年4月达到了历史新高,自那以后,人们对机器学习的兴趣并没有下降多少。


但实际上学习机器学习是很困难的。你要么使用像“黑匣子”一样的预先构建的软件包,在那里你输入数据,魔术就会从另一端出来,要么你必须处理高级数学和线性代数。这两种方法都使机器学习既具有挑战性又令人生畏。


本教程旨在向你介绍机器学习的基本概念。随着你的跟进,你将从头构建你的第一个模型来进行预测,同时准确地理解你的模型是如何工作的。


什么是机器学习?


简而言之,机器学习是构建系统(称为模型)的实践,这些系统可以使用数据进行训练,以发现模式,然后使用这些模式对新数据进行预测。


与许多其他编程不同,机器学习模型不是一个基于规则的系统。基于规则的系统,使用一系列“if/then”语句来确定结果(例如,“如果学生旷课超过50%,那么他们就会自动不及格”)。

相反,机器学习模型检查一个具有定义结果的数据集中的数据点之间的统计关系,然后应用它所学习到的关于这些关系的知识来分析和预测一个新数据集中的结果。


机器学习的原理


为了更好地理解机器学习的基础知识,我们先来看一个例子。假设我们正在卖房子,我们想确定一个合适的挂牌价格。我们可能要做的——以及房地产经纪人实际上要做的——是看看我们所在地区已经售出的类似房屋。用机器学习的术语来说,我们看到的每一栋房子都是一个观测值。


对于每一栋房子,我们都要考虑一些因素,比如房子的大小,有多少间卧室和浴室,离杂货店等设施有多远等等。在机器学习术语中,这些属性中的每一个都称为特征。


一旦我们找到了一些类似的房子,我们就可以看看它们的售价,把这些价格平均起来,就能对我们自己房子的价值做出一个相当合理的预测。


查看类似的房子有助于我们确定自己房子的价格


在这个例子中,我们建立的“模型”是根据我们所在地区其他房屋的数据(观察数据)进行训练的,然后用它来预测我们房屋的价值。我们预测的价值,即价格,被称为目标变量。


当然,这个例子并不是真正的“机器学习”,因为我们根据自己房子的特点,选择了“观察”房子来学习。试图在更大的范围内做这类事情——比如基于大型房地产数据集预测城市中任何一栋房屋的价格——对人类来说都是极其困难的。观察和特征越多,手工分析就越困难,也就越容易忽略数据中那些重要但不明显的模式。

这就要用到机器学习了。一个真正的机器学习模型可以在更大的范围内做类似于我们的小房子预测模型这样的事情:


  1. 查看过去的房屋销售的大量数据集(观测值)

  2. 寻找一所房子的特点(特征)和它的价格(目标变量)之间的模式和统计关系,包括可能对正在查看数据的人来说不明显的模式

  3. 使用这些统计关系和模式来预测基于我们提供给它的数据的任何新房的价格。


我们将在本教程中构建的模型与我们上面所概述的类似。我们将使用Python构建一个简单的模型来生成Airbnb的公寓租金推荐。


(本文假定你熟悉Python的pandas库——如果你需要重温pandas,这里推荐我们的两部分pandas教程博客文章或交互式Python和Pandas课程。)


预测Airbnb的租金


对于外行人来说,Airbnb是一个短期房屋和公寓租赁的互联网市场。例如,它可以让你在外出时将房子出租一周,或者将空余的卧室出租给旅行者。自2008年成立以来,该公司就发展迅速,其估值已接近400亿美元,目前市值超过全球任何一家连锁酒店。


Airbnb房东面临的一个挑战是确定最优的夜间租金。在许多地区,潜在的租房者会看到一系列不错的房源清单,可以根据价格、卧室数量、房间类型等标准进行筛选。由于Airbnb是一个市场,主人每晚可以收取的费用与市场的动态密切相关。以下是一个Airbnb搜索体验的截图:


Airbnb 搜索结果


假设我们想在Airbnb上出租一个房间。作为房东,如果我们试图收取高于市场价格的租金,租户会选择更实惠的替代品,而我们就不会赚到钱。另一方面,如果我们把每晚的租金定得太低,我们就会失去潜在的收入。


我们怎么才能找到中间的“最佳位置”呢?我们可以使用的一个策略是:


  • 找到一些与我们房间相似的清单,

  • 把与我们最相似的房间的标价平均一下,

  • 并将我们的标价设置为这个计算出的平均价格。


但是一遍又一遍地那样手动操作将会非常耗时,毕竟我们是数据科学家!我们不需要手工操作,而是要构建一个机器学习模型,使用一种称为k最近邻(KNN)的技术来自动化这个过程。


我们先来看一下我们要处理的数据集。


我们的Airbnb数据


Airbnb没有公布其市场上的房源数据,但一个名为Inside Airbnb的独立组织从该网站上许多主要城市的房源样本中提取了数据。在这篇文章中,我们将使用他们的来自于2015年10月3日的有关美国首都华盛顿特区房源价格列表的数据集。这里是一个到该数据集的直链。http://data.insideairbnb.com/united-states/dc/washington-dc/2015-10-03/data/listings.csv.gz  )


数据集中的每一行都是一个特定的房源页面,代表华盛顿特区Airbnb上可租用的房源。用机器学习的术语来说,每一行都是一个观察。 这些列描述了每个房源页面的不同特性(用机器学习术语来说,是特征)。


为了减少处理数据集的麻烦,我们删除了原始数据集中的许多列,并将文件重命名为 dc_airbnb.csv。


以下是我们想要使用的一些最重要的列(特征),因为这些都是租户可能用来评估他们将选择哪一个房源页面的特点:


  • accommodates(住宿):出租房屋可容纳的客人人数

  • bedrooms(卧室):包括在出租房屋内的卧室数

  • bathrooms(卫生间):包含在出租房屋内的卫生间数量

  • beds(床位):包含在出租房租中的床位数量

  • price(价格):每晚租金

  • minimum_nights:客人可入住的最短租期

  • maximum_nights:客人可入住的最长租期

  • number_of_reviews:前一位客人留下的评论数量


我们首先将清理后的数据集读入pandas,打印它的大小并查看前几行。(如果你不确定如何从原始数据集中删除多余的列,请查看一些我们的pandas和数据清理课程)。



这看起来不错! 现在,我们来看看我们将用于机器学习模型的算法.


K最近邻算法


K最近邻(KNN)算法的工作原理类似于我们前面概述的三步过程,该过程将我们的出租房屋与类似房源进行比较,并取平均价格。让我们来看看它的一些细节:


首先,我们选择要进行比较的类似房源的数量,k。

其次,我们需要使用一个相似性指标来计算每个房源与我们的房屋之间的相似性。

第三,我们使用相似性指标对每个房源进行排序,并选择前k个房源。


最后,我们计算这k个类似房源的平均价格,并将其作为我们的出租价格。

为了简单起见,上面的图片的每个观察只使用了两个特征(卧室数和价格)来与我们的房源进行比较,而机器学习的好处在于,我们可以通过评估每个观察的更多特征来进行更复杂的比较。


让我们通过定义我们将要使用的相似性度量来开始构建我们的真实模型。然后,我们将实现k最近邻算法,并使用它来给出一个新房源的价格。出于本教程的目的,我们将使用一个固定的k值5,但是一旦你熟悉了这个算法的工作流,你就可以对这个值进行试验,看看用更低或更高的k值是否可以得到更好的结果。


Here’s the general formula for Euclidean distance: d=(q1−p1)2+(q2−p2)2+⋯+(qn−pn)2 where q1 to qn represent the feature values for one observation and p1 to pn represent the feature values for the other observation.


欧氏(欧几里得)距离


当试图预测像价格这样的连续值时,使用的主要相似性指标是欧氏距离。欧氏距离的一般公式为:

其中q1到qn表示一个观测值的特征值,p1到pn表示另一个观测值的特征值。


如果你感觉脑袋要炸了,别担心! 我们将把它分成更小的部分。我们先来看…


建立一个基本的KNN模型


让我们从分解开始,从我们的数据集中只看一列。这里是一个特征的公式:

平方根和平方幂消掉了,公式简化为:

用文字来表达就是,我们想要找到该观测值和我们想要对我们正在使用的这个特征进行预测的数据点之间差异的绝对值。


就我们目前的目的而言,假设我们想出租的居住空间可以容纳三个人。


我们首先只使用accommodates特征来计算数据集中第一个居住空间与我们自己的居住空间之间的距离。我们可以使用NumPy函数np.abs() 来获得绝对值。



最小的可能的欧氏距离是零,这意味着我们与之比较的观测值和我们的观测值是一样的,所以我们这里得到的结果是有意义的。但是,单独来看,如果我们不知道这个值与其他值相比结果如何,那么这个值就没有多大意义。让我们计算数据集中每个观测值的欧式距离,并使用 pd.value_counts() 来查看我们已经得到的值的范围。



其中有461个房源的距离为0,因此可以容纳与我们的出租房屋相同的人数。这些房源可能是一个很好的开始点。


如果我们只使用距离为0的前5个值,我们的预测将偏向于数据集的现有顺序。相反,我们将随机化观测值的顺序,然后选择距离为0的前5行。我们将使用 DataFrame .sample() 来随机化行。这个方法通常用于选择DataFrame的一个随机部分,但是我们将告诉它随机选择100%,这会为我们随机打乱行。


我们还将使用 random_state 参数,它为我们提供了一个可重复的随机顺序,因此任何人都可以使用它,并得到完全相同的结果。



在我们取平均价格之前,你将注意到价格列有 object 类型,因为价格有美元符号和逗号(上面的示例没有显示逗号,因为所有的值都小于$1000)。


在计算前五个值的平均值之前,让我们通过删除这些字符并将其转换为 float 类型来清理这一列。我们将使用pandas的Series.str.replace() 来删除孤立的字符,并传递正则表达式  \$|,   ,它将匹配$ 或, 。



现在,我们已经做出了第一个预测——我们的KNN模型告诉我们,当我们仅使用accommodates特征为我们的三人居出租房屋找到合适的价格时,我们应该将我们的公寓标价为88.00美元。


这是一个好的开始!问题是,我们没有任何方法知道这个模型有多精确,这使得对它进行优化和改进是不可能的。在不评估任何机器学习模型的准确性的情况下,参照它的预测结果都不是一个好主意!


评估我们的模型


检验模型质量的一个简单方法是:


  • 将数据集分成2部分:

        ◆ 一个训练集:包含大多数行(75%)

        ◆ 一个测试集:包含剩余的少数行(25%)

  • 使用训练集中的行来预测测试集中行的价格值。

  • 将预测值与测试集中的实际价格值进行比较,看看预测值有多准确。


我们将采用这种方法,将我们的3723行数据集分成两部分:  train_df 和 test_df,以75%-25%的比例进行分割。

将数据分成训练和测试数据集两部分


我们还将删除前面创建第一个模型时添加的列。



为了使我们在查看指标时更容易,我们将把前面创建的模型合并到一个函数中。我们不需要担心随机化这些行,因为它们仍然是之前随机化的。



现在,我们可以通过这个函数使用 accommodates 列来预测我们测试数据集的值。



使用RMSE来评估我们的模型


对于许多预测任务,我们希望处罚那些离实际值较远的预测值,而不是那些离实际值较近的预测值。


为此,我们可以取误差值平方的均值,即均方根误差(RMSE)。下面是RMSE的公式:


其中n表示测试集中的行数。这个公式第一眼看上去感觉很困难,但我们所需要做的是:


  • 取每一个预测值与实际值(error)之差,

  • 对这个值进行平方(square),

  • 取所有差值的平方的平均值(mean),并

  • 取均值的平方根(root)。


因此,从下到上的读: root mean squared error(均方根误差)。我们来为我们在测试集中所做的预测计算RMSE值。



我们的RMSE大约是213美元。关于RMSE的一个方便的事情是,由于我们进行了平方然后取平方根,因此,RMSE的单位和我们预测的值是一样的,这使得我们很容易理解误差的标度。


在这种情况下,这个标度是相当大的-我们距离得到一个准确的预测还差得远。


比较不同模型


我们可以使用误差度量来查看模型的准确性,让我们使用不同的列创建一些预测,并查看误差是如何变化的。



我们可以看到,在我们训练的四个模型中,使用accomodates列的模型是最好的。


然而,我们得到的误差率相对于我们数据集中房源的价格范围来说是相当高的。带有这种误差率的预测并不怎么有用!


谢天谢地,我们还能做点其他事情! 到目前为止,我们只使用一个特征来训练我们的模型,称为单变量模型。为了更加准确,我们可以让它同时评估多个特征,这就是多变量模型。


我们将读取这个数据集的一个已清理版本,这样我们就可以专注于评估模型。在我们清理过的数据集中:


  • 所有列都已被转换为数值,因为我们无法计算一个带有非数值字符的值的欧氏距离。

  • 为了简单起见,我们删除了非数字列。

  • 任何带有缺失值的房源清单都已被删除。

  • 我们对列进行了标准化,这样会得到更准确的结果。


如果你想阅读更多关于机器学习的数据清理和数据准备的内容,你可以阅读这篇优秀的博文: 《为机器学习准备和清理数据》。


让我们看一下这个清理过的版本,它被称为 dc_airbnb. normalized.csv,并预览前几行:



然后我们将随机化这些行,并将其分成训练和测试数据集。



计算多个特征的欧氏距离


我们来回忆一下最初的欧式距离方程是什么样子的:


我们先建立一个使用 accommodates 和 bathrooms 特征的模型。在这种情况下,我们的欧式方程应该是:


为了找到两个居住空间之间的距离,我们需要计算两个accommodates值之间的差值平方,两个bathrooms值之间的差值平方,将它们相加,然后对结果的和取平方根。


下面是 normalized_lists 中前两行之间的欧式距离:



到目前为止,我们一直在通过自己写出方程的逻辑来自己计算欧氏距离。我们可以使用scipy.spatial中的 distance.euclidean() 函数来代替这些操作。它以两个向量为参数,计算它们之间的欧氏距离。euclidean()函数需要:


  • 使用一个类列表对象(Python列表、NumPy数组或pandas的Series)来表示的两个向量

  • 这两个向量都必须是一维的,并且有相同数量的元素


让我们使用euclidean()函数来计算一下数据集中第1行和第5行之间的欧式距离,进行实践一下。




英文原文:https://www.dataquest.io/blog/machine-learning-tutorial/ 
译者:好酒不上头
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/36312
 
331 次点击