繁体   English   中英

机器学习回归的局限性?

[英]Limitations of Regression in Machine Learning?

我最近一直在学习 ML 的一些核心概念,并使用 Sklearn 库编写代码。 经过一些基本练习后,我尝试了来自 kaggle 的 AirBnb NYC 数据集(大约有 40000 个样本) - https://www.kaggle.com/dgomonov/new-york-city-airbnb-open-data#New_York_City_。 PNG

我尝试制作一个 model,它可以根据数据集的各种特征预测房间/公寓的价格。 我意识到这是一个回归问题,并使用这个 sklearn 备忘单,我开始尝试各种回归模型。

在此处输入图像描述 我使用 sklearn.linear_model.Ridge 作为基线,在做了一些基本的数据清理之后,我在测试集上得到了 0.12 的糟糕 R^2 分数。 然后我想,也许线性 model 太简单了,所以我尝试了适用于回归的“内核技巧”方法(sklearn.kernel_ridge.Kernel_Ridge),但它们需要太多时间来适应(> 1hr),以应对这种情况。 我使用 sklearn.kernel_approximation,Nystroem function 来逼近 kernel map。 但是,在训练之前将转换应用于特征,然后使用简单的线性回归 model。 如果我增加了 n_components 参数,那么即使这样也需要花费大量时间来转换和拟合,而我必须获得任何有意义的准确性提高。

所以我现在在想,当你想对一个巨大的数据集进行回归时会发生什么? kernel 技巧在计算上极其昂贵,而线性回归模型过于简单,因为实际数据很少是线性的。 那么神经网络是唯一的答案还是我缺少一些聪明的解决方案?

PS我刚刚开始使用溢出,所以请让我知道我可以做些什么来改善我的问题!

这是一个很好的问题,但由于它经常发生,对于复杂的问题没有简单的答案。 回归并不像经常出现的那样简单。 它涉及许多假设,并且不限于线性最小二乘模型。 需要几门大学课程才能完全理解它。 下面我将写一篇关于回归的快速(但远非完整)备忘录:

  • 没有什么能取代正确的分析。 这可能涉及专家访谈以了解您的数据集的限制。
  • 您的 model(任何 model,不限于回归)仅与您的功能一样好。 如果房价取决于当地税率或学校评级,那么即使是完美的 model 没有这些功能也不会表现良好。
  • model 在设计上无法包含某些功能,因此永远不要期望在现实世界中获得满分。 例如,实际上不可能考虑到杂货店、餐馆、俱乐部等的访问。这些特征中的许多也是移动目标,因为它们往往会随着时间而变化。 如果人类专家的表现更差,即使是 0.12 R2 也可能很棒。
  • 模型有它们的假设。 线性回归期望因变量(价格)与独立变量(例如财产大小)线性相关。 通过探索残差,您可以观察到一些非线性并用非线性特征覆盖它们。 然而,有些模式很难被发现,但仍然可以通过其他模型解决,例如非参数回归和神经网络。

那么,为什么人们仍然使用(线性)回归?

  • 它是最简单最快的 model。 对实时系统和统计分析有很多影响,所以这很重要
  • 通常它被用作基线 model。 在尝试一种花哨的神经网络架构之前,了解与简单方法相比我们改进了多少会很有帮助。
  • 有时回归用于测试某些假设,例如效应的线性和变量之间的关系

总而言之,回归在大多数情况下绝对不是终极工具,但这通常是首先尝试的最便宜的解决方案

UPD,以说明关于非线性的观点。

建立回归后,您计算残差,即回归误差predicted_value - true_value 然后,为每个特征制作一个散点图 plot,其中横轴是特征值,纵轴是误差值。 理想情况下,残差具有正态分布,不依赖于特征值。 基本上,错误往往小而不是大,并且在 plot 中类似。

它应该是这样的:

正态残差

这仍然是正常的 - 它仅反映样本密度的差异,但误差具有相同的分布:

这些残差也是正常的

这是一个非线性示例(周期性模式,添加 sin(x+b) 作为特征):

残差中的非线性模式

非线性的另一个例子(添加平方特征应该有帮助):

残差的另一种非线性模式

以上两个例子可以描述为不同的残差均值取决于特征值。 其他问题包括但不限于:

  • 不同的方差取决于特征值
  • 残差的非正态分布(误差为 +1 或 -1、簇等)

上面的一些图片是从这里拍摄的:

http://www.contrib.andrew.cmu.edu/~achoulde/94842/homework/regression_diagnostics.html

对于初学者来说,这是一本关于回归诊断的好书。

我会试一试这个。 看看我嵌入在代码中的注释/评论。 请记住,这只是我测试的一些想法。 您可以尝试各种其他事情(获取更多数据,测试不同的模型等)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
#%matplotlib inline
import sklearn
from sklearn.linear_model import RidgeCV, LassoCV, Ridge, Lasso
from sklearn.datasets import load_boston
#boston = load_boston()

# Predicting Continuous Target Variables with Regression Analysis
df = pd.read_csv('C:\\your_path_here\\AB_NYC_2019.csv')
df

# get only 2 fields and convert non-numerics to numerics
df_new = df[['neighbourhood']]
df_new = pd.get_dummies(df_new)
# print(df_new.columns.values)

# df_new.shape
# df.shape

# let's use a feature selection technique so we can see which features (independent variables) have the highest statistical influence on the target (dependent variable).
from sklearn.ensemble import RandomForestClassifier
features = df_new.columns.values
clf = RandomForestClassifier()
clf.fit(df_new[features], df['price'])

# from the calculated importances, order them from most to least important
# and make a barplot so we can visualize what is/isn't important
importances = clf.feature_importances_
sorted_idx = np.argsort(importances)

# what kind of object is this
# type(sorted_idx)
padding = np.arange(len(features)) + 0.5
plt.barh(padding, importances[sorted_idx], align='center')
plt.yticks(padding, features[sorted_idx])
plt.xlabel("Relative Importance")
plt.title("Variable Importance")
plt.show()

在此处输入图像描述

X = df_new[features]
y = df['price']


reg = LassoCV()
reg.fit(X, y)
print("Best alpha using built-in LassoCV: %f" % reg.alpha_)
print("Best score using built-in LassoCV: %f" %reg.score(X,y))
coef = pd.Series(reg.coef_, index = X.columns)

print("Lasso picked " + str(sum(coef != 0)) + " variables and eliminated the other " +  str(sum(coef == 0)) + " variables")

结果:

Best alpha using built-in LassoCV: 0.040582
Best score using built-in LassoCV: 0.103947
Lasso picked 78 variables and eliminated the other 146 variables

下一步...

imp_coef = coef.sort_values()
import matplotlib
matplotlib.rcParams['figure.figsize'] = (8.0, 10.0)
imp_coef.plot(kind = "barh")
plt.title("Feature importance using Lasso Model")


# get the top 25; plotting fewer features so we can actually read the chart
type(imp_coef)
imp_coef = imp_coef.tail(25)
matplotlib.rcParams['figure.figsize'] = (8.0, 10.0)
imp_coef.plot(kind = "barh")
plt.title("Feature importance using Lasso Model")

在此处输入图像描述

X = df_new
y = df['price']


from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 10)

# Training the Model
# We will now train our model using the LinearRegression function from the sklearn library.

from sklearn.linear_model import LinearRegression
lm = LinearRegression()
lm.fit(X_train, y_train)

# Prediction
# We will now make prediction on the test data using the LinearRegression function and plot a scatterplot between the test data and the predicted value.
prediction = lm.predict(X_test)
plt.scatter(y_test, prediction)


from sklearn import metrics
from sklearn.metrics import r2_score
print('MAE', metrics.mean_absolute_error(y_test, prediction))
print('MSE', metrics.mean_squared_error(y_test, prediction))
print('RMSE', np.sqrt(metrics.mean_squared_error(y_test, prediction)))
print('R squared error', r2_score(y_test, prediction))

结果:

MAE 1004799260.0756996
MSE 9.87308783180938e+21
RMSE 99363412943.64531
R squared error -2.603867717517002e+17

这太可怕了,嗯。 我们知道这行不通。 让我们试试别的。 我们仍然需要使用数字数据来计算,所以让我们试试 lng 和 lat 坐标。

X = df[['longitude','latitude']]
y = df['price']

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 10)

# Training the Model
# We will now train our model using the LinearRegression function from the sklearn library.

from sklearn.linear_model import LinearRegression
lm = LinearRegression()
lm.fit(X_train, y_train)

# Prediction
# We will now make prediction on the test data using the LinearRegression function and plot a scatterplot between the test data and the predicted value.
prediction = lm.predict(X_test)
plt.scatter(y_test, prediction)

df1 = pd.DataFrame({'Actual': y_test, 'Predicted':prediction})
df2 = df1.head(10)
df2
df2.plot(kind = 'bar')

在此处输入图像描述

from sklearn import metrics
from sklearn.metrics import r2_score
print('MAE', metrics.mean_absolute_error(y_test, prediction))
print('MSE', metrics.mean_squared_error(y_test, prediction))
print('RMSE', np.sqrt(metrics.mean_squared_error(y_test, prediction)))
print('R squared error', r2_score(y_test, prediction))
# better but not awesome

结果:

MAE 85.35438165291622
MSE 36552.6244271195
RMSE 191.18740655994972
R squared error 0.03598346983552425

让我们看看OLS:

import statsmodels.api as sm
model = sm.OLS(y, X).fit()


# run the model and interpret the predictions
predictions = model.predict(X)
# Print out the statistics
model.summary()

在此处输入图像描述

我会假设以下几点:

一种热编码正在做它应该做的事情,但它并不能帮助你得到你想要的结果。 使用 lng/lat 的性能稍好一些,但这也不能帮助您获得想要的结果。 如您所知,您必须使用数字数据来解决回归问题,但没有任何功能可以帮助您预测价格,至少不是很好。 当然,我可能在某个地方犯了错误。 如果我确实犯了错误,请告诉我!

查看下面的链接,了解使用各种功能预测房价的一个很好的例子。 注意:所有变量都是数字,结果相当不错(大约 70%,给予或接受,但仍然比我们在 Air BNB 数据集上看到的要好得多)。

https://bigdata-madesimple.com/how-to-run-linear-regression-in-python-scikit-learn/

https://towardsdatascience.com/linear-regression-on-boston-housing-dataset-f409b7e4a155

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM