人工智能—美国加利福尼亚州房价预测实战

引言

在当今快速发展的房地产市场中,房价预测已成为一个至关重要的领域。它不仅关系到投资者的决策,也直接影响到普通购房者的生活质量。特别是在美国加利福尼亚州,这个以其高房价和房地产市场的波动性而闻名的地方,准确的房价预测显得尤为重要。本文将通过实战案例,深入探讨如何利用数据分析和机器学习技术来预测加利福尼亚州的房价走势。

背景信息

加利福尼亚州房地产市场概况
加利福尼亚州,作为美国经济最发达的地区之一,其房地产市场长期以来一直是国内外投资者关注的焦点。从硅谷的高科技产业到洛杉矶的娱乐业,再到旧金山的金融中心,加利福尼亚州的经济多元化为房地产市场提供了坚实的基础。然而,与经济活力相伴的是房价的高涨和快速波动,这给市场参与者带来了不小的挑战。

数据集信息

美国加利福尼亚州房价数据集是一个公开的数据集,通常用于机器学习和数据科学项目中的回归分析。根据搜索结果,这个数据集包含以下特征(本文涉及数据集已绑定上传,可免费获取):

  • 经度(Longitude):表示房屋所在位置的经度坐标。
  • 纬度(Latitude):表示房屋所在位置的纬度坐标。
  • Housing Median Age:区域中房屋的中位年龄,即一半房屋比这个年龄新,一半房屋比这个年龄旧。
  • Total Rooms:该区域内所有房屋的房间总数。
  • Total Bedrooms:该区域内所有房屋的卧室总数,这个特征可能存在缺失值。
  • Population:该区域内的总人口数。
  • Households:该区域内的家庭总数。
  • Median Income:该区域内家庭的收入中位数。
  • Median House Value:该区域内房屋的中位数价格,通常作为目标变量用于预测。

数据挖掘目标

通过房子的信息特征,预测Median House Value(该区域房价中位数)。

数据的读入和初步分析

数据读入:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
import seaborn as sns 
import plotly as py
import plotly.graph_objs as go
import warnings
import os
warnings.filterwarnings("ignore")
data = pd.read_csv('housing.csv')
data.head()

展示前五行数据:
在这里插入图片描述

描述性统计:
在这里插入图片描述
分割测试集与训练集:

from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)

老规矩80%数据用于训练,20%数据用于测试。

数据的初步分析:

# 设置图形窗口的大小为宽度15英寸,高度9英寸。  
plt.figure(3 , figsize = (15 , 9))    
# 初始化一个计数器n,用于跟踪当前正在处理的列(或子图)的索引。  
n = 0     
# 遍历DataFrame data的所有列名。  
for x in data.columns.to_list():       # 对每一列,增加计数器n的值。  n += 1        # 创建一个子图,在3行3列的网格中,位置由n决定(注意:这里需要确保n的值在1到9之间,否则会出现错误)。  plt.subplot(3 , 3 , n)        # 调整子图之间的间距。注意:通常最好在循环外只调用一次subplots_adjust,因为它会调整整个图形中所有子图的布局。  # 这里的调用可能不会有预期的效果,因为它在每次迭代时都会重新设置。  plt.subplots_adjust(hspace =0.5 , wspace = 0.5)        # 使用seaborn的distplot函数绘制data中当前列x的分布图,并设置直方图的bin数量为20。  # 注意:seaborn的distplot函数在较新版本中已被displot取代。  sns.distplot(data[x] , bins = 20)        # 为当前子图设置标题,标题内容为“Distplot of ”,后面跟着当前列的名称x。  plt.title('Distplot of {}'.format(x))    
# 显示所有子图。  
plt.show()

9个变量的直方图展示:
在这里插入图片描述
直方图是一种统计图表,用于表示数据分布的可视化。它通常用于展示数据集中数值型数据的分布情况。以下是直方图的一些关键特点和解释方法:

  • 数据分组:首先,将数据分成若干个连续的、通常是等宽的区间或“箱子”(bins)。
  • 箱子高度:每个箱子的高度表示落在该区间内的数据点的数量,即频数。
  • 连续性:与条形图不同,直方图的箱子是连续的,没有间隙,因为它们表示的是数值型数据的连续区间。
  • 范围:每个箱子覆盖一个特定的数值范围,例如,在房价数据中,一个箱子可能代表20万美元到30万美元的价格区间。
  • 频率分布:直方图可以展示数据的频率分布,即不同数值区间内数据点的集中程度。
  • 形状识别:通过直方图的形状,可以识别数据的分布特性,如是否对称、是否存在偏斜(右偏或左偏)、是否有双峰(双模态)等。
  • 密度曲线:有时在直方图上叠加一个平滑的曲线,称为核密度估计(KDE),它可以更平滑地展示数据的分布。

分析:

  • 通过观察直方图,可以快速了解数据的中心趋势、分散程度和分布形态,为进一步的统计分析提供直观信息。
  • 多变量比较:直方图也可以用来比较不同组别的数据分布,只需为每组数据创建一个直方图并并排显示。
  • 局限性:直方图的一个局限性是选择箱子的宽度和位置可能会影响图表的解释。不同的箱子设置可能会展示出数据的不同特征。

直方图是数据分析中的重要工具,特别是在探索性数据分析(EDA)阶段,它帮助数据分析师快速把握数据的关键特征

绘制经度和纬度的散点图:经纬度的二维分布也就是实际的地形分布。

散点图多用于相关性分析,具体介绍请查看我的专栏《从0开始学统计》内的从0开始学统计-什么是相关?

# 经度与纬度关系图
sns.relplot(data=data,x="longitude",y="latitude")

在这里插入图片描述
绘制房价随人口数量变化的折线图:

# 房价随人口变化折线图
data.plot('population', 'medianHouseValue')    
plt.show()

在这里插入图片描述简单的图形我就不介绍了,感兴趣可以在网上查。

绘制皮尔逊相关系数热力图:

# 设置seaborn的绘图样式和字体,这里设置了绘图上下文为"paper"(适合论文的样式)和字体为"monospace"(等宽字体)  
sns.set(context="paper",font="monospace")    
# 计算DataFrame 'data' 中各列之间的相关系数,并将结果存储在'housing_corr_matrix'中  
housing_corr_matrix = data.corr()  # 注意:这里假设'data'是已经加载好的一个DataFrame    
# 设置matplotlib的图形和坐标轴。这里创建了一个图形对象'fig'和一个坐标轴对象'axe'(但注意,这里应该是'ax'而不是'axe')  
# figsize参数设置了图形的大小为12x8英寸  
fig, ax = plt.subplots(figsize=(12,8))  # 修改'axe'为'ax'    
# 使用seaborn的diverging_palette函数生成一个颜色映射(cmap),从颜色220(接近蓝色)渐变到颜色10(接近红色)  
# center参数设置为"light",表示颜色映射的中心是亮色  
# as_cmap=True表示返回的是一个颜色映射对象  
cmap = sns.diverging_palette(220,10,center = "light", as_cmap=True)    
# 使用seaborn的heatmap函数绘制热力图。这里使用了之前计算的相关系数矩阵'housing_corr_matrix'  
# vmax参数设置了颜色映射的最大值,这里为1(因为相关系数范围是-1到1)  
# square=True表示每个单元格都是正方形  
# cmap参数指定了使用的颜色映射  
# annot=True表示在每个单元格中显示数值  
sns.heatmap(housing_corr_matrix, vmax=1, square=True, cmap=cmap, annot=True)    
# 显示图形  
plt.show()

在这里插入图片描述
之前的案例有介绍怎样辨识相关热图,这里就不再重复了,感兴趣可以翻下以前的案例。

在经纬图上绘制房屋价格和人口分布:

# 使用Pandas的DataFrame.plot()方法绘制散点图  
# kind="scatter" 指定了绘制的是散点图  
# x="longitude" 指定了x轴的数据是'longitude'列  
# y="latitude" 指定了y轴的数据是'latitude'列  
# alpha=0.4 设置了点的透明度,使得重叠的点可以部分可见  
# s=data["population"]/50 设置了点的大小,大小与'population'列的值成正比,但除以50是为了缩放大小  
# label="population" 设置了图例的标签为"population"(但通常这个标签可能更适合用于s参数,表示大小与人口相关)  
# figsize=(10,7) 设置了图形的大小为10x7英寸  
# c=data["medianHouseValue"] 设置了点的颜色,颜色由'medianHouseValue'列的值决定  
# cmap=plt.get_cmap("jet") 设置了颜色映射为"jet"  
# colorbar=True 在图上显示颜色条,表示不同的颜色对应的'medianHouseValue'值  
# sharex=False (在.plot()方法中,sharex通常不是有效的参数,除非您在子图网格中使用subplot_kws或gridspec_kws)  
# 如果是在使用subplot或subplots时,sharex可能用于控制x轴是否共享    
data.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4,  s=data["population"]/50, label="population (size)", figsize=(10,7),  c=data["medianHouseValue"], cmap=plt.get_cmap("jet"), colorbar=True,  # sharex=False  # 在这个上下文中,sharex参数不适用,可以移除  
)    
# plt.legend() 显示图例,图例通常显示在图的某个角落,根据label参数来标识不同的数据系列  
plt.legend()

在这里插入图片描述上图点越密集,对应区域的颜色就越深,通过颜色深浅就可以看出数据的几种区域。越大、透明度越低的地方代表人口越多,越接近colorbar顶端的颜色的地方代表房产价格越高。经过这一系列分析后,对数据可以有非常直观的了解。

拆分数据:

housing=train_set.drop("medianHouseValue",axis=1)
labels=train_set["medianHouseValue"].copy()

得到输入数据和目标变量(label)。

数据标准化:采用z-score标准化,之前博客有过介绍,感兴趣的可以点超链接进入。

# 从 sklearn.impute 模块中导入 SimpleImputer 类,这个类用于填充数据集中的缺失值。  
from sklearn.impute import SimpleImputer    
# 从 sklearn.preprocessing 模块中导入 StandardScaler 类,这个类用于数据的标准化处理,即将数据转换为均值为0,标准差为1的分布。  
from sklearn.preprocessing import StandardScaler    
# 从 sklearn.pipeline 模块中导入 Pipeline 类,这个类用于构建数据处理的流水线,可以按照定义的顺序依次执行多个数据转换步骤。  
from sklearn.pipeline import Pipeline    
# 创建一个 Pipeline 对象,其中包含了 SimpleImputer 和 StandardScaler  
pipeline = Pipeline([  ('imputer', SimpleImputer(strategy="median")),  # 使用 SimpleImputer,策略为中位数填充  ('scaler', StandardScaler()),  # 使用 StandardScaler 进行标准化  
])  
data_prepared = pipeline.fit_transform(housing)#最终的结果,为numpy数组

在这里插入图片描述
上图为标准化后的5组数据。

模型构建

查看不同模型的表现

# 从 sklearn.linear_model 模块中导入 LinearRegression, ElasticNet, 和 Lasso 类。这些类分别代表线性回归、弹性网络(结合了L1和L2正则化的线性回归)和Lasso回归(L1正则化的线性回归)。  
from sklearn.linear_model import LinearRegression, ElasticNet, Lasso    
# 从 sklearn.ensemble 模块中导入 RandomForestRegressor 类。这是一个基于随机森林的回归模型。  
from sklearn.ensemble import RandomForestRegressor    
# 从 sklearn.pipeline 模块中导入 make_pipeline 函数(尽管在您的代码中并未直接使用它)。make_pipeline 是一个快捷方式来创建 pipeline。  
from sklearn.pipeline import make_pipeline    
# 从 sklearn.model_selection 模块中导入 KFold 和 cross_val_score 函数。KFold 用于生成K折交叉验证的索引,cross_val_score 用于计算模型的交叉验证得分。  
from sklearn.model_selection import KFold, cross_val_score    
# 设定交叉验证的折数为10  
n_folds = 10    
# 定义一个函数 get_rmse,该函数接收一个模型作为参数,并返回模型在数据上的均方根误差(RMSE)。  
# RMSE 是通过计算 cross_val_score 的负均方误差的平方根来获得的,因为 cross_val_score 默认返回的是负指标,所以需要先取负值再平方根。  
def get_rmse(model):  rmse = np.sqrt(-cross_val_score(model, data_prepared, labels, scoring="neg_mean_squared_error", cv=n_folds))  return rmse    
# 创建四个不同的回归模型实例:  
# linreg 是线性回归模型  
linreg = LinearRegression()    
# forest 是随机森林回归模型,设置了10个决策树估计器和随机状态为42  
forest = RandomForestRegressor(n_estimators=10, random_state=42)    
# lasso 是Lasso回归模型,设置了正则化强度为0.0005和随机状态为1  
lasso = Lasso(alpha=0.0005, random_state=1)    
# enet 是弹性网络模型,设置了正则化强度为0.0005,L1和L2正则化的比例为0.9,以及随机状态为3  
enet = ElasticNet(alpha=0.0005, l1_ratio=.9, random_state=3)    
# 使用之前定义的 get_rmse 函数来计算并打印每个模型的RMSE  
print(get_rmse(linreg))  
print(get_rmse(forest))  
print(get_rmse(lasso))  
print(get_rmse(enet))

在一般的训练中,通常可以选取多个模型,通过计算误差得出最好的模型。在本案例中,对线性回归、随机森林、Lasso、ElasticNet模型进行训练,得出了随机森林(random forest regressor)的效果是最好的,因为它的均方根误差最小。

在这里插入图片描述
选择效果最好的模型进行展示:

# 从测试数据集 test_set 中删除 "medianHouseValue" 列(这通常是因为我们要对这部分数据进行预测,而不是作为特征),  
# axis=1 表示我们是在列的方向上进行操作(即删除列)。  
# 结果存储在 test_housing 变量中,它只包含用于预测的特征,但不包含目标变量 "medianHouseValue"。  
test_housing = test_set.drop("medianHouseValue", axis=1)    
# 从测试数据集 test_set 中复制 "medianHouseValue" 列的值,这列通常是我们想要预测的目标变量。  
# 使用 copy() 方法是为了确保我们得到的是原始数据的副本,而不是视图或引用,以避免后续可能的数据修改。  
# 结果存储在 test_labels 变量中,它包含了与 test_housing 对应的真实目标值。  
test_labels = test_set["medianHouseValue"].copy()    
# 使用之前定义的 pipeline 对象(它可能包含了数据预处理步骤,如缺失值填充和标准化)来拟合(fit)并转换(transform)  
# test_housing 数据集。注意,这里我们只使用了 transform 方法而不是 fit_transform,  
# 因为 pipeline 已经通过训练集进行了拟合(通常在之前的数据准备步骤中)。  
# 结果(即预处理后的特征)存储在 test_data 变量中,这些特征将用于后续的模型预测。  
test_data = pipeline.transform(test_housing)

在这里插入图片描述

下面代码对测试集数据进行处理:

# 使用RandomForestRegressor(随机森林回归模型)的fit方法,将预处理后的训练数据(data_prepared)和对应的标签(labels)作为输入,  
# 对模型进行训练。fit方法会计算每个决策树所需的参数,并构建整个随机森林模型。  
forest.fit(data_prepared, labels)    
# 使用训练好的RandomForestRegressor模型的predict方法,对预处理后的测试数据(test_data)进行预测。  
# predict方法会返回测试数据集中每个样本的预测值,这些预测值存储在predict_labels变量中。  
predict_labels = forest.predict(test_data)

训练数据和预测:

# 使用RandomForestRegressor(随机森林回归模型)的fit方法,将预处理后的训练数据(data_prepared)和对应的标签(labels)作为输入,  
# 对模型进行训练。fit方法会计算每个决策树所需的参数,并构建整个随机森林模型。  
forest.fit(data_prepared, labels)    
# 使用训练好的RandomForestRegressor模型的predict方法,对预处理后的测试数据(test_data)进行预测。  
# predict方法会返回测试数据集中每个样本的预测值,这些预测值存储在predict_labels变量中。  
predict_labels = forest.predict(test_data)

对实际数据和预测数据进行可视化:

# 假设您已经导入了NumPy库(import numpy as np)和Matplotlib的pyplot模块(import matplotlib.pyplot as plt)。  
# 这行代码将test_labels(可能是一个Pandas Series或列表)转换为NumPy数组,并存储在origin_labels变量中。  
# 这样做是为了确保数据类型与Matplotlib兼容,并可能为了后续的数值操作。  
origin_labels = np.array(test_labels)    
# 使用Matplotlib的plot函数绘制origin_labels数组的前100个值。  
# 这通常用于可视化原始数据的标签值,以便与预测值进行比较。  
# label参数为这条线指定了一个标签,该标签稍后会显示在图例中。  
plt.plot(origin_labels[0:100], label='origin_labels')    
# 使用Matplotlib的plot函数绘制predict_labels数组的前100个值。  
# 这用于可视化模型的预测值,以便观察预测结果与实际标签之间的差异。  
# 同样,通过label参数为这条线指定了一个标签。  
plt.plot(predict_labels[0:100], label='predict_labels')    
# 显示图例,其中包含了之前通过label参数指定的标签。  
# 图例会解释图中的每条线分别代表什么。  
plt.legend()

在这里插入图片描述
比较预测和实际结果(红棕色线为预测数据,蓝色为实际数据),可以看出模型的预测能力还是相当不错的,当然有更多的数据,我相信预测结果会更加准确。

大家可能觉得看图没有感觉,我就给大家把预测数据合并到表内,给大家展示预测完全正确的部分数据(见下图,倒数第二列为实际结果,最后一列为预测结果)。

在这里插入图片描述

创作不易,点赞、关注、评论、转发4连!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TF-IDF、BM25传统算法总结

1. TF-IDF算法 F-IDF(词频-逆文档频率)是一种用于衡量文本中词语重要性的方法,特别适用于信息检索和文本挖掘任务。下面会拆分为两部分深入讲解TF-IDF的计算过程,以便更好地理解。 TF-IDF的计算过程可以分为两个主要部分&#xf…

【漏洞复现】契约锁电子签章平台 add 远程命令执行漏洞(XVE-2023-23720)

0x01 产品简介 契约锁电子签章平台是上海亘岩网络科技有限公司推出的一套数字签章解决方案。契约锁为中大型组织提供“数字身份、电子签章、印章管控以及数据存证服务”于一体的数字可信基础解决方案,可无缝集成各类系统,让其具有电子化签署的能力,实现组织全程数字化办公。通…

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系(m_coord)

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系(m_coord) 0. 引言1. m_proj使用方法2. 结语 0. 引言 上一篇介绍了m_proj函数用于初始化投影,本篇介绍的函数m_coord用于初始化地理坐标系或地磁坐标系,地理/地磁坐标系和投影…

xss一些笔记

(乱写的一些笔记) innerHTML只防script像是img就不会防 innerText都防 上面代码执行避免用户交互 js也可以用’‘执行 例子 alert’1‘ document.location.hash // #号后的部分,包括#号 document.location.host // 域名…

黑马苍穹外卖4 店铺营业状态设置+Redis基础

店铺营业状态设置 Redis MySQL Java并发 JavaMVC 计算机网络 操作系统 算法,后端面试主要是这些,外加项目 Redis 数据库,基于内存存储的key-value结构。 mysql是磁盘存储,通过二维表存储。 在文件夹目录打开cmd 服务端&#xf…

YOLOv10(6):YOLOv10基于TensorRT的部署(基于INetworkDefinition)

1. 写在前面 我们在前面已经讲过很多关于YOLOv10的一些知识点,也简单理了一下如何训练自己的数据。 现在本篇文章主要是讲解一下如何在TensorRT中部署YOLOv10,相信经过这一步,各位小伙伴已经能够无限的接近于将YOLOv10产品化了。 另一个需要说…

LeetCode-day17-2713. 矩阵中严格递增的单元格数

LeetCode-day17-2713. 矩阵中严格递增的单元格数 题目描述示例示例1:示例2:示例3: 思路代码 题目描述 给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat,你可以选择任一单元格作为 起始单元格 。 从起始单元格出发&#xff…

Perplexity AI — 探索网络,发掘知识,沟通思想

体验地址:Perplexity AI (国外网站访问需要梯子) Perplexity AI是一款功能强大的人工智能搜索引擎,其特点和优势主要体现在以下几个方面: 功能: 自然语言搜索:Perplexity AI可以理解用户的自然…

Shopify 如何实现 Sticky 功能

Shopify 如何实现 Sticky 功能 介绍 在网页设计中,Sticky 功能是一种常见的技术,它使得网页上的元素在滚动时保持固定位置。这对于创建吸引人的用户体验和提高网站的可用性非常重要。Shopify 作为一个流行的电商平台,提供了丰富的功能和工具…

进化版ChatGPT的Siri今年无缘上线!苹果正打造史上最薄iPhone 17

目录 01 超强Siri助手预计2025年上线 02 集成ChatGPT但没有买单 03 iPhone 17更轻薄 最新报道称,苹果的AI功能将在未来几个月逐步推出,并持续到2025年。 据称,今年夏天结束前,开发者们仍无法试用和体验。 因此,在即…

MySQL系列-语法说明以及基本操作(一)

1、前言 主要讲解MySQL的基本语法 官网文档 https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html 关于MySQL的基本语法,关于数据类型、表的操作、数据操作、事务、备份等,可参考 http://www.voidme.com/mysql 2、数据类型 数…

Oracle中递归查询(START WITH……CONNECT BY……)

一、基本语法 在Oracle中START WITH……CONNECT BY……一般用来查找存在父子关系的数据,也就是树形结构的数据。 SELECT * FROM TABLE WHERE 条件3 START WITH 条件1 CONNECT BY 条件2;start with [condition]:设置起点,用来限制第一层的数…

线程间通信

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 我们已经知道进程之间不能直接共享信息,那么线程之间可以共享信息吗?我们通过一个例子来验证一下。定义一个全局变量g_num&am…

【腾讯云智笔试题——分苹果两种解法】

文章目录 题目描述解题思路:疑惑解析代码中明明是两个嵌套的for循环时间复杂度为什么是O(m)? 题目描述 有m个苹果,n个小孩。每个小孩都有一个编号,小明的编号是。要尽量公平的分苹果,相邻编号的…

C++ 类与对象的使用要点(超详细解析,小白必看系列)

1.面向过程和面向对象初步认识 C语言是面向过程的语言,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题 例如:洗衣服 C是基于对象的,关注的是对象,将一件事拆分成不同的对象,靠对…

[NewStarCTF 2023 公开赛道]R!C!E!

好久没写了。今天儿弄一个rce 题很直接&#xff0c;好久没这么直白的题了&#xff0c;看源码 <?php highlight_file(__FILE__); if(isset($_POST[password])&&isset($_POST[e_v.a.l])){$passwordmd5($_POST[password]);$code$_POST[e_v.a.l];if(substr($password…

amov无人机连接;+数据传输;啊啊啊啊啊

socket传输数据: 局域网连接 连接---通信(命令行直接;)--- 传输数据(socket)--传输内容:launch文件; qgc连接; 1.局域网下的通信 1.1 局域网 厂家提供的方式是通过Homer图数传工具(硬件)构建的amov局域网实现通信连接. 好处是通信距离足够长,支持150m;坏处是"局部&qu…

电脑提示d3dcompiler_47.dll丢失的解决方法,实测靠谱的5种方法

在计算机使用过程中&#xff0c;缺失d3dcompiler_47.dll这一系统文件是一个常见问题&#xff0c;尤其是对于游戏和图形密集型应用程序用户来说尤为重要。这个文件是DirectX软件工具包的一部分&#xff0c;主要用于处理图形渲染的应用程序接口的核心元素。当你在运行游戏或某些软…

如何定制Spring的错误json信息

一&#xff0c;前言 相信很多同学都有遇到过这样的spring错误信息。 在我们没有做catch处理时或者做全局的exceptionHandle时&#xff0c;Spring遇到抛出向外的异常时&#xff0c;就会给我们封装返回这么个格式的异常信息。 那么问题来了&#xff0c;我们能否对这个返回增加错…