如何使用机器学习、React 和 Django 从头开始​​创建用于房地产价格估算的 Web 应用程序?

如何使用机器学习、React 和 Django 从头开始​​创建用于房地产价格估算的 Web 应用程序?

脚本可在此处获得: https://gitlab.com/spam.mahdi/paris-real-estate-price-prediction

本文的目的是与您分享使用 React 和 Django 创建一个 Web 应用程序来运行我的机器学习算法:巴黎公寓价格的估算器。

文章将分为两部分:

  • 创建机器学习算法来获得我们的预测器。根据公寓的特征,我们的算法将预测公寓的价格。
  • 创建 Web 应用程序以使用户可以访问我们的算法。用户将有机会填写具有公寓特征的表格以获取价格。如果他想预测几套公寓的价格,用户将能够上传一个 Excel 文件。

An apartment in Paris (Not mine, in fact, it’s a little bit too expensive for me)

通过在互联网上进行一些研究,当我发现这一点时,我感到非常惊讶 法国政府每 6 个月提供一次包含法国所有房地产交易的清洁数据集。 这里是访问它的链接: https://www.data.gouv.fr/fr/

在我收集了这些数据后,我的目的是使用最新的技术来处理它, 我的目的是使用 django rest 框架构建一个 react.js 应用程序来运行我的机器学习模型。

我将根据其特点(大小、房间数量和本地化)预测公寓价格。

该项目将遵循以下计划:

  • 数据探索
  • 构建机器学习模型
  • 使用 React 和 Django 创建应用程序
  1. 数据探索

在构建模型之前,我们需要分析我们的数据集以了解特征之间的关系并清除异常值。

通过这张图表,我们可以看到多年来在巴黎售出的公寓数量和价格非常稳定。这意味着它将是 一个经典的回归问题 并且时间序列将没有用。

但是通过这张表,我们可以看到公寓的价格随着时间的推移而上涨。要在我们的数据集中拥有这些信息, 我们将创建一个分类列 如果公寓在 2014 年出售,则需要 1,2015 年需要 2,2016 年需要 3,依此类推。因此,我们将有一个 与公寓价格和销售年份呈线性关系 .

为了更好地理解我们的数据,最后要做的事情是 相关分析 .我们将计算 斯皮尔曼相关 在价格和其他功能之间。我们使用这种相关性度量而不是 pearson 的度量,因为它在分类变量上效果很好。

Spearman’s rank correlation coefficient

我们发现本地化、大小和房间数量是最能解释其价格的特征 .这意味着在对特征进行一些预处理之后,我们将能够建立一个机器学习模型来根据公寓的特征来预测其价格。

2.建立机器学习模型

A. 预处理

在训练模型之前, 我们需要清理数据集,因为我们有两种异常值

  • 非常昂贵的公寓(豪华是另一个市场,我们想要一个适用于标准公寓的模型)
  • 非常便宜的公寓(我们看到公寓以一欧元的象征性价格出售)

在这里我们可以看到我们之前的数据集 预处理 , 异常值使得无法捕捉到大小和价格之间的线性关系。为了解决这个问题,我通过计算大小和价格之间的比率来删除每个异常值。

Price and size of apartments before pre-processing

现在,我们可以很容易地找到价格和尺寸之间的线性关系 ,一个简单的线性回归应该有一个不错的 r²。

Price and size of apartments afterpre-processing

此外,不要删除缺少大小和房间数列的每一行, 我们通过训练算法来估算缺失值,以便在必要时填充这些列。

但我们不想只用两列来预测价格,否则使用机器学习算法将毫无用处。解释价格的其他变量是位置,此信息存储在区和分区列中。巴黎分为 20 个区,每个区都有自己的分区('parcelle')。 要使用此信息,我们将需要使用 one-hot 编码器。

One-hot 编码将分类变量转换为向量。例如,如果我们有 3 个标签:“黄色”、“黑色”、“紫色”,它将创建 3 个这样的向量:黄色:[1,0,0]、黑色:[0,1,0]、紫色:[0,0,1]。有了这个,我们从 4 个可用功能增加到 3501 个。

在训练我们的模型之前要做的最后一件事是标准化我们的数据。 为此,我们将在特征上使用最小最大缩放器来提高模型的性能。事实上,它有助于优化梯度下降等过程。

现在,我们已经准备好使用机器学习模型的干净数据集。

B. 训练模型

我们想要预测的值 (y) 是巴黎公寓的价格,我们有 13 501 个特征 (X) 来解释这个变量。 使用这些数据,我们将训练 3 个模型:

  • 随机森林
  • 支持向量机
  • XGBoost

为我们的每个模型提供最佳参数, 我们将使用具有以下值的网格搜索:

对于随机森林,我们决定微调这些参数:

  • max_depth :树的最大深度。

  • max_features:每次分割的最大特征数

  • min_samples_leaf:创建叶子所需的最小样本数

  • min_samples_split:拆分节点所需的最小样本数

  • n_estimators:树的数量。

    rfc_parameters = [{
    'max_depth' : [20, 30, 40],
    'max_features' : [0.15, 0.2, 0.25],
    'min_samples_leaf' : [1, 3, 4],
    'min_samples_split' : [10, 20, 30],
    'n_estimators' : [50, 100, 150]
    }]

对于支持向量机,我们决定微调这些参数:

  • C:正则化参数

  • degree:多项式核函数的度数

  • 内核:算法中使用的内核类型(多项式、径向基函数)

    svr_parameters = [{
    'C' : [0.1, 1, 10],
    '度':[2,3],
    '内核':['poly','rbf']
    }]

对于 XGBoost,我们决定微调这些参数:

  • colsample_bytree:每棵树使用的列的百分比

  • gamma:创建进一步分区所需的最小损失减少

  • learning_rate:用于避免过拟合的收缩参数

  • max_depth:树的最大深度

  • min_child_weight:一个孩子所需样本的最小总和

    xgb_parameters = [{
    'colsample_bytree': [0.5, 0.7, 0.8],
    ‘伽玛’:[0.7, 1, 1.5],
    'learning_rate': [0.05, 0.1, 0.15],
    'max_depth': [3, 4, 5],
    'min_child_weight': [3, 4, 5]
    }]

R² of the different models

而不是在这 3 个模型之间做出选择, 最好的办法是使用 Stacking 合并它们 .事实上,这些模型并不完全基于相同的数学公式,因此,为了防止过度拟合,我们将对这 3 个预测进行平均。

R² of the stacking model

现在,我们有了我们的模型,我们只需要创建一个后端来启动我们的模型和一个前端来显示我们的结果以拥有我们的 Web 应用程序。

3. 使用 React 和 Django 创建应用

现在,我们有了一个不错的模型,但是为了让用户可以访问它,我们需要创建一个 Web 应用程序。这个想法很简单。我们想要创建一个屏幕,用户可以在其中放置公寓的信息以获取价格估算。

用户必须有两种方式填写公寓信息:

  • 通过直接在屏幕上输入
  • 通过上传文件

这是 Web 应用程序的外观:

Interface to get price prediction for a single apartment

Interface to upload a file containing apartments information

A. 后端

首先,我们将使用 django 创建我们的后端 API。

首先,有必要获取我们的文件夹,然后我们将键入以下命令:

 $ django-admin 启动项目 ModelBackend

创建文件夹后,我们只需要修改两个脚本:views 和 urls。

视图.py

 从 django.shortcuts 导入渲染  
 从 django.http 导入 JsonResponse  
 导入json  
 将熊猫导入为 pd  
 从 firstPage.modele.connect_api 导入 api_connection  
 from firstPage.modele.back_end 导入预测  
 从 django.core.files.storage 导入 FileSystemStorage def scoreJson(请求):  
 输入 = json.loads(request.body)  
 gmaps = api_connection().connect_to_api()  
 pred = 预测(输入['nb_piece'],输入['surface'],输入['adresse'],输入['dep'])  
 包裹 = 'AB'  
 价格 = pred.pred(parcelle)[0]  
 return JsonResponse({'price':"{:,.2f}".format(round(price, 2))}) def scoreFile(请求):  
 fileObj = request.FILES['filePath']  
 fs=文件系统存储()  
 filePathName=fs.save(fileObj.name,fileObj)  
 文件路径名=fs.url(文件路径名)  
 文件路径='.'+文件路径名  
 gmaps = api_connection().connect_to_api()  
 输入 = pd.read_csv(filePath, sep='\t')  
 list_prediction=[]  
 对于索引,input.iterrows() 中的行:  
 pred = 预测(行['nb_piece'],行['表面'],行['地址'],行['dep'])  
 包裹 = 'AB'  
 价格 = pred.pred(parcelle)[0]  
 list_prediction.append("{:,.2f}".format(round(price, 2)))  
 返回 JsonResponse({"list_price":list_prediction})

网址.py

 从 django.contrib 导入管理员  
 from django.urls 导入路径  
 从 firstPage 导入视图  
 从 django.views.decorators.csrf 导入 csrf_exempt 网址模式 = [  
 路径('admin/',admin.site.urls),  
 path('scoreJson', csrf_exempt(views.scoreJson), name='Score Application'),  
 path('scoreFile', csrf_exempt(views.scoreFile), name ='Score File'),  
 ]

要启动后端,我们必须在终端上输入:

 python3 manage.py 运行服务器

B. 前端

现在,我们只需为用户创建一个前端界面,以使我们的算法可以访问。

我们将使用 React。要启动项目,需要键入以下命令:

 npx create-react-app 前端-ui

我们将创建 Web 应用程序的两个页面:

  • 主页,用户可以直接在屏幕上显示公寓信息以获取价格估算
  • 用户可以上传 Excel 文件以获取多个公寓的价格估算的页面

主页.json。

 导入'./App.css';  
 从'react/cjs/react.development'导入{组件}; 功能首页(){  
 返回 (  
 <div className="Home">  
 <h1>输入属性的特征</h1>  
 <JsonForm/>  
 </div>  
 );  
 } 导出默认主页; 类 JsonForm 扩展组件{  
 构造函数(道具){  
 超级(道具);  
 this.state={nb_piece:"", 表面:"", 地址:"", dep:""}; this.handleChange = this.handleChange.bind(this);  
 this.handleSubmit = this.handleSubmit.bind(this);  
      
      
 } 处理变化(事件){  
 // console.log(event.target.name+' '+event.target.value);  
 this.setState({[event.target.name]:event.target.value});  
 } 处理提交(事件){  
 event.preventDefault();  
 //this.setState({price:10})  
 常量 url="[ http://localhost:8000/scoreJson](http://localhost:8000/scoreJson) ";  
          
 常量 bodyData=JSON.stringify({  
 “nb_piece”:this.state.nb_piece,  
 “表面”:this.state.surface,  
 “地址”:this.state.adresse,  
 “dep”:this.state.dep,  
 });  
 const reqOpt = {method:"POST", headers:{"Content-Type":"application/json"}, body: bodyData};  
 获取(网址,reqOpt)  
 .then((resp) => resp.json())  
 .then((respJ) => this.setState({price:respJ.price}))  
 } 使成为(){  
 返回 (  
 <div>  
 <form onSubmit={this.handleSubmit}>  
 <table>  
 <tbody> <tr><td>nb_piece:</td><td>  
 <input type="text" value={this.state.nb_piece} name="nb_piece" onChange={this.handleChange}></input></td></tr>  
 <tr><td>表面:</td><td>  
 <input type="text" value={this.state.surface} name="surface" onChange={this.handleChange}></input></td></tr>  
 <tr><td>地址:</td><td>  
 <input type="text" value={this.state.adresse} name="adresse" onChange={this.handleChange}></input></td></tr>  
 <tr><td>部:</td><td>  
 <input type="text" value={this.state.dep} name="dep" onChange={this.handleChange}></input></td></tr>  
                     
 </tbody>  
 </table>  
 <input type="submit" value="提交" ></input>  
 </form>  
 <div><h3>预估价格为:{this.state.price}</h3></div>  
 </div>  
 );  
 }  
 }

以及导入excel文件的页面:

 导入'./App.css';  
 从'react/cjs/react.development'导入{组件}; 函数上传表单(){  
 返回 (  
 <div className="UploadForm">  
 <h1>文件下载:</h1>  
 <FormBatch />  
 </div>  
 );  
 } 导出默认 UploadForm; 类 FormBatch 扩展组件{  
 构造函数(道具){  
 超级(道具);  
 this.state = {selectFile:null, output:false,respFromServer:null}; this.handleFile = this.handleFile.bind(this);  
 this.handleUpload = this.handleUpload.bind(this);  
 } 处理文件(事件){  
 console.log(event.target.value);  
 this.setState({[event.target.name]:event.target.files[0]}); } 处理上传 = 异步事件 => {  
 event.preventDefault();  
 常量网址=“[ http://127.0.0.1:8000/scoreFile](http://127.0.0.1:8000/scoreFile) ";  
 const fileToSend = this.state.selectFile;  
 console.log(fileToSend);  
 var formdata = new FormData();  
 formdata.append("filePath", this.state.selectFile, this.state.selectFile.name);  
 const reqOpt={method:"POST", body:formdata}; const resp = await fetch(url, reqOpt);  
 const resp2 = 等待 resp.json(); this.setState({respFromServer:resp2.list_price});  
 this.setState({output:true}); } 使成为(){  
 const iterateData = this.state.respFromServer;  
 常量 checkPoint = this.state.output;  
 让 finalTableData  
      
 如果(检查点){  
 常量表数据 = iterateData.map((x) =>  
 <tr><td>{X}</td></tr>  
 ); 最终表格数据=<table>  
 <tbody>  
 <tr><td>大奖赛</td></tr>  
 {表数据}  
 </tbody>  
 </table>  
 }  
 别的{  
 finalTableData="无响应"  
 } 返回 (  
 <div>  
 <form onSubmit={this.handleUpload}>  
 <input type="file" name="selectFile" onChange={this.handleFile}></input>  
 <input type="submit" value="苏梅特"></input>  
 </form>  
 <div>{finalTableData}</div>  
 </div> );  
 }  
 }

完成,要显示我们的前端应用程序,我们只需输入:

 纱线开始

结论

我们看到了创建运行机器学习算法的 Web 应用程序的每个步骤:

  • 数据收集和探索性数据分析
  • 清洗与特征工程
  • 型号的选择
  • 使用 Django 创建后端
  • 使用 React 创建前端

为了改进这个项目,他们有很多可能的事情,其中​​一些是:

  • 可以通过添加更多数据来改进模型,例如有关邻居(学校、地铁等)的信息
  • 前端很简单,但我们可以添加更多页面,让它更漂亮
  • 我们可以更进一步,尝试将项目部署在云上。

我的脚本在这里可用: https://gitlab.com/spam.mahdi/paris-real-estate-price-prediction

如果您有任何问题或建议,请随时通过linkedin与我联系: www.linkedin

感谢您的阅读

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/39810/39272909

posted @ 2022-09-29 09:41  哈哈哈来了啊啊啊  阅读(160)  评论(0编辑  收藏  举报