计算机系统应用教程网站

网站首页 > 技术文章 正文

回归or分类?线性or逻辑?它们到底有什么不同?

btikc 2024-10-25 10:54:06 技术文章 6 ℃ 0 评论
全文共7366字,预计学习时长30分钟或更长




图片来源:https://techdifferences.com/wp-content/uploads/2018/01/Untitled-2.jpg

回归 VS 分类


为确定使用回归还是分类模型,首先要问的问题是:

目标变量是一个量,一个二进制分类的概率,还是一个标签?


如果目标变量是一个量或概率,须应用回归模型。这意味着如果要推测量值,如高度、收入、价格和分数,使用的模型应该输出一个连续数字。或者,如果目标变量是某一项二进制标签的概率(判断好坏的概率除外),那么也应该选择回归模型,只是具体使用的模型略有不同。我们用均方差(MSE或其它误差)和均方根误差(RMSE或标准差)来评估此类模型,以量化模型中的误差。


如果目标变量是一个标签,则应该使用分类模型。分类有助于预测观察标签(好中差等标签除外)。棘手之处在于判断目标变量是否为标签。比方说,如果目标变量是一个顺序变量,表示1至5之间的不同等级,那么它们即为标签,但其同时具有数学意义。


这意味着数据的平均值和偏差仍有意义,但若要进行推测,应用分类模型是更为明智的选择。我们通过F分数或精确度来评估这些模型,而非其误差或标准差。下面的谱系可以帮助我们理解有多少观察被正确标注,而通过混淆矩阵,这些观察得到视觉化呈现。矩阵中,观察被分为真阳性/真阴性/假阳性/假阴性。



混淆矩阵


运行模型做出预测之前,理解目标变量的特征尤为重要。若应该使用分类模型却误用了回归模型,会得出一堆连续的预测,而非离散标签。而因为大多数(或全部)预测并非你想得出的1或0值,会导致推测出一个较低的F分数(也可能为0)。如果使用得出概率的逻辑模型,有一个方法是设定一个边界值。比如,假定任何大于0.9的值即为1,任何小于0.9的值为0,你仍然会得出一个F分数和混淆矩阵。但使用合适的模型通常可以避免这项额外的步骤。


一旦决定了要使用的方法,接下来就要选择模型进行预测。



回归模型


回归模型中使用最普遍的是线性回归和逻辑回归。

基本的线性回归模型遵循这个众所周知的等式y=mx+b,但通常实际应用中形式略有不同:

y=β?+β?x?+…+β?x?

该等式中,β?代表纵轴截距,即全部解释变量为0值时的y值。β?到β?是x?到x?变量的相关系数,若其它变量不变,x?到x?中有一项增加或减少,则y值随之增减。比如,在y=1+2x?+3x?这个等式中,若x?由0变为1,x?不变,则y至由1变为3。


逻辑模型遵循的等式略有不同:

y= 1 / (1+e^-(β?+β?x?+…+β?x?))

其中y值在0到1之间。因此,逻辑模型通常被用来分析二进制目标变量。此种情况下,目标变量值为0或1,或者目标变量是二进制变量的概率。正如前面提到,此等式防止出现非逻辑预测,得出的概率低于0或高于1。



两种标准模型均可被调整,以更好拟合数据。主要方法是包含惩罚参数。线性和逻辑回归模型对应的等式均包含全部输入的变量,而这很可能会导致过度拟合。如果数据拟合过度,模型得出预测的可靠性会降低,并局限于训练样本。为了避免此种情况的出现,可以进行特征选择,挑选出相对重要的特征;或在模型中引入惩罚参数。



引入L2惩罚项会产生岭回归模型。在此模型中,相对无关变量的系数较少,以限制其影响,但仍包含所有输入的变量。如果想无视变量的相关性并把每一个变量包含进模型中,以上操作十分有效。但大多数情况下,你会倾向于尽可能简化的模型。


引入L1惩罚项会产生拉索回归模型。拉索模型的机制与岭回归模型相似,但会把不相关变量的系数缩减至0,完全消除其影响。而拉索模型的不足之处在于观察数(n)比变量数(k)多,其最多可包含n个变量。同时,拉索模型对相关变量的处理有局限,只能随机保留其中一个变量。


弹性网络回归模型可以解决以上所有问题,它可以结合两个惩罚项,更好地处理多维数据和多重共线性问题。因此,弹性网络模型通常会比拉索模型更精确,但这取决于其所选的L1惩罚项比例,即其超参数之一。


最后还有一个问题,即严格意义上目标变量可能不是解释变量的线性功能。对此,有两个解决方法:更高层级的回归模型或随机森林回归模型。


比方说,在最初的数据探测阶段,你发现要预测收入时,年龄与收入的关联更偏向于二次关系,而非线性关系。在这种情况下,会对原来的线性等式中引入一个二阶变量。等式就变成了这种形式:

y=β?+β?x+β?x2


随后你再次应用模型。你仍然可以应用线性回归模型或更高层级的模型。

一个常见的误解是:线性回归模型仅能产生线性功能。但其实,线性回归模型中的“线性”是指相关系数之间的关系,而非变量本身。因此,在模型中包含更高的层级或互动有助于解释变量之间的关系。但要注意的是,如果这样做,必须保证最终等式中包含低层级和主要影响变量,无论它们是否重要。避免出现这样的等式:

y=β?+β?x2 或y=β?+β?x?*x?


我们也可以使用随机森林回归模型(如下图所示),后文将会更详细地介绍其替代模型——应用更广泛的随机森林分类。随机森林回归的机制与逻辑回归相似,二者均可得出二进制标签的概率。简单来说,随机森林回归会产生大量决策树。这些决策树都会得出预测,而最终预测结果为最普遍的预测或平均预测。


现在你可能会想,难道不能用这些模型预测概率目标变量吗?如果训练组的y值在0到1之间,那么模型的预测y值也在0到1之间,是吧?是,也不是。


大多数情况下,模型预测的y值都在0到1之间。但如果模型为线性,则低于0或高于1的概率值是非逻辑回归的。你可以在模型建构中付出110%的努力,但一个观察被分为某一类的概率不可能达到110%。


而且,在线性模型中,诊断患病的概率分别为10%和15%的人群之间的不同就相当于诊断患病概率为95%和1%的人群之间的不同。显然,如果某人100%患病,那么这一点在线性模型中就不会体现,因为此数据对于低于50%的概率而言影响极小。


分类模型


如果分析是为了构建模型以预测观察标签,那么就得使用分类模型。最简单的分类模型就是逻辑模型。然而,通过创建假目标变量并对各变量应用逻辑模型,我们能够训练非二进制目标变量的逻辑模型。你也可以对此逻辑模型导入L1和L2惩罚项,从而运行拉索和岭逻辑模型。


随机森林分类则更有助于推测。和随机森林回归一样,随机森林分类包含仅在特定情况下有影响的特征。随机森林分类的机制同上,其采取决策树的概念以创建一个随机森林,并随机选择变量,最终基于森林得出预测。在应用模型的编码中,可以看到许多超参数,比如决策树的数量、每一片树叶上的最小观察数、最大分裂数、决策树的最大深度等。这些超参数有助于构建一个更为精准的模型,但随机森林仍有可能过度拟合。如果决策树太大,那么它们很可能过于具体,因此无法应用于测试组。



最后,创建神经网络也有助于预测观察标签。这是最为复杂的方法,但相比其他方法的确有某些优势。其主要优势在于可促成无监督学习。这意味着无需先前标记的训练数据,该算法即可根据检测到的相似点来聚合组别。尽管创建起来很复杂,神经网络在预测标签方面更为精确,这一点对于利害关系重大的预测十分重要,如疾病诊断和诈骗检测。


本质上,神经网络算法的工作机制是引入一组数据,找到其中的模型和趋势,然后做出预测(受监督)或聚合组别(无监督)。通过重复此流程并引入更大的训练组,神经网络算法愈加精确。但要注意避免创建过多网络层级导致训练组过度拟合。



总结


选择预测模型时,首要考虑的问题是目标变量的特征。目标变量是持续的还是离散的?变量是量还是标签?变量是概率还是类别?变量与所有解释变量存在线性相关性吗?需要在预测中包含所有的变量吗?思考这些问题的答案有助于你挑选出最佳预测模型。



源代码及运行对比:


Regression

In [0]:
import sklearn
from sklearn.linear_model import ElasticNet, Lasso, Ridge, LogisticRegression, LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.ensemble import RandomForestRegressor
import pandas as pd
import matplotlib
from matplotlib import pyplot
def warn(*args, **kwargs):
 pass
import warnings
warnings.warn = warn

In [0]:
from google.colab import files
uploaded = files.upload()

In [0]:
data = pd.read_csv("avocado.csv")
data = data.drop(['Unnamed: 0','Date', 'region','Total Volume','Total Bags'], axis = 1)
data = pd.get_dummies(data, drop_first=True)
y = data['AveragePrice']
X = data.drop('AveragePrice', axis=1)
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=.1)

In [250]:
lm = LinearRegression()
lm_fit = lm.fit(X_train, y_train)
lm_predict = lm_fit.predict(X_test)
 
#lr = LogisticRegression()
#lr_fit = lr.fit(X_train,y_train)
#lr_predict = lr_fit.predict(X_test)
## will not work because the range of y is 0 to 3.25, not 0 to 1
 
ridge = Ridge()
ridge_fit = ridge.fit(X_train,y_train)
r_predict = ridge_fit.predict(X_test)
 
lasso = Lasso(max_iter=1000)
lasso_fit = lasso.fit(X_train,y_train)
l_predict = lasso_fit.predict(X_test)
 
ENet = ElasticNet(l1_ratio=.01)
ENet_fit = ENet.fit(X_train,y_train)
en_predict = ENet_fit.predict(X_test)
 
## there are no higher order variables in this dataset, but for the sake of exemplifying the procedure,
## pretend there is a quadratic relationship between the number of 4225 avocados and the price
data1 = data.head(500)
data1['4225_sq'] = 0
for i in range(len(data1['4225'])):
 data1['4225_sq'][i] = (data1['4225'][i])**2
y2 = data1['AveragePrice']
X2 = data1.drop('AveragePrice', axis=1)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X2,y2, test_size=.1)
lm_fit = lm.fit(X_train2, y_train2)
ho_predict = lm_fit.predict(X_test2)
 
rand = RandomForestRegressor()
rand_fit = rand.fit(X_train,y_train)
rf_predict = rand_fit.predict(X_test)
/usr/local/lib/python3.6/dist-packages/sklearn/ensemble/forest.py:245: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
 "10 in version 0.20 to 100 in 0.22.", FutureWarning)
In [252]:
print('Linear Model MSE:' , mean_squared_error(y_test,lm_predict))
#mean_squared_error(y_test,lr_predict)
print('Ridge Model MSE:' , mean_squared_error(y_test,r_predict))
print('Lasso Model MSE:' , mean_squared_error(y_test,l_predict))
print('Elastic Net Model MSE:',mean_squared_error(y_test,en_predict))
print('Higher Order Model MSE:' ,mean_squared_error(y_test2,ho_predict))
print('Random Forest MSE:' ,mean_squared_error(y_test,rf_predict))
Linear Model MSE: 0.09792038897928204
Ridge Model MSE: 0.09791772364668704
Lasso Model MSE: 0.14654262570004578
Elastic Net Model MSE: 0.12919487097231586
Higher Order Model MSE: 0.015512612920132457
Random Forest MSE: 0.034497292054794515

Classification

In [0]:
import sklearn
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, confusion_matrix
import pandas as pd
In [0]:
from google.colab import files
uploaded = files.upload()

In [0]:
data = pd.read_csv("train.csv")
data = data.drop(['Name','Ticket','Cabin'], axis=1)
data = pd.get_dummies(data)
data = data.fillna(0)
 
y = data['Survived']
X = data.drop('Survived', axis=1)
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=.1)
In [236]:
data.head()
Out[236]:
In [0]:
lr = LogisticRegression()
lr_fit = lr.fit(X_train,y_train)
 
lasso2 = LogisticRegression(penalty='l1')
lasso2_fit = lasso2.fit(X_train,y_train)
 
ridge2 = LogisticRegression(penalty='l2')
ridge2_fit = ridge2.fit(X_train,y_train)
 
rand_for = RandomForestClassifier(n_estimators = 500, random_state = 40)
rand_for_fit = rand_for.fit(X_train,y_train)
 
clf = MLPClassifier(activation='logistic', solver='lbfgs',learning_rate='adaptive', alpha=.0005)
clf_fit = clf.fit(X_train, y_train)

In [273]:
print('Logistic F Score:',lr_fit.score(X_test, y_test))
print('LASSO F Score:',lasso2_fit.score(X_test, y_test))
print('Ridge F Score:',ridge2_fit.score(X_test, y_test))
print('Random Forest Classifier F Score:',rand_for_fit.score(X_test, y_test))
print('Neural Net F Score:',clf_fit.score(X_test, y_test))
Logistic F Score: 0.8555555555555555
LASSO F Score: 0.8555555555555555
Ridge F Score: 0.8555555555555555
Random Forest Classifier F Score: 0.8777777777777778
Neural Net F Score: 0.7333333333333333

留言 点赞 关注

我们一起分享AI学习与发展的干货

欢迎关注全平台AI垂类自媒体 “读芯术”

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表