首页 理论教育 Python与AI编程(下):解决线性回归问题

Python与AI编程(下):解决线性回归问题

时间:2023-11-08 理论教育 版权反馈
【摘要】:线性回归模型y是一个单变量,即小费值。例如这一桌的人数、客人的性别、小费总额、是否吸烟、星期几、午餐还是晚餐等,我们假定是线性关系,即人数越多,小费越高,就可以采用线性回归模型来进行预测。

Python与AI编程(下):解决线性回归问题

当我们在国外餐厅用餐时,经常需要给小费。下面是一个预测在餐厅用餐时给小费的例子,这个例子来自seaborn库。

这里采用线性回归方法,它是一个非常简单的监督学习算法,这个方法可处理具有线性关系的数据。假定我们有一组数据(x,y),它们具有线性关系(两个变量之间存在一次方函数关系),我们就可以采用线性回归模型y=kx+b来进行预测。

线性回归模型

y是一个单变量,即小费值。小费的多少和什么有关呢?例如这一桌的人数、客人的性别、小费总额、是否吸烟、星期几、午餐还是晚餐等,我们假定是线性关系,即人数越多,小费越高,就可以采用线性回归模型来进行预测。如果对于一个问题,我们用线性模型得到的效果不太好,可以考虑采用非线性模型进行模拟。

下面给出建立模型并进行预测的步骤。

● 首先需要准备数据。

● 其次对数据进行预处理,例如,将一些文本量转成模型易处理的数字量,对缺失数据进行一定的处理。

● 再次对数据进行划分,一部分用于训练模型,另一部分用于校验选择模型(或者参数)。

● 最后使用建立好的模型对新的输入进行预测。

小费(tips)数据面面观

在进行建模之前,我们一般需要对数据有一些认识,比如,包含多少组数据,每项数据包括哪些指标,数据的存储类型是什么,这是一些通用的问题。针对具体的数据,例如小费数据,我们可以想到研究小费的目的是什么?如果是打零工,可以看看哪一天得到的小费多一些,某一天中服务哪种桌型或者顾客得到的小费可能会多一些。带着这些问题,我们在这一节中首先对数据进行一定的描述和分析,在下一节我们将介绍如何建立模型。

下面是数据分析部分的程序和说明。该程序参考http://devarea.com/pythonmachine-learning-example-linear-regression/。

----------------------part 1 准备工作----------------------

#导入相应的库,如果没有安装,可以采用pip install 进行安装

import matplotlib.pyplot as plt

import seaborn as sb

import pandas as pd

--------------------part 2数据基本信息--------------------

df=sb.load_dataset('tips')#下载数据

df.head()#前5项数据

df.info()#数据结构

df.sample(5)#随机给出5组数据

df.describe()#数据统计

----------------------part 3数据分析----------------------

#Tips数据分析,最累的一天,小费最多的情况(哪天,哪种顾客,哪种桌型)

#哪一天工作最累?df

df.groupby('day').count()#按day进行分组

#哪一天给的小费最多以及百分比最高?df2

df2=df.groupby('day').sum()#用sum()函数计算每天小费的总和(df2是一个数据表

df2.drop('size',inplace=True,axis=1)#st去掉size项

df2['percent']=df2['tip']/df2['total_bill']*100 #增加一列百分比数据(小费占总账单的百分比)

#哪种顾客给的小费最多?吸烟者还是非吸烟者?df3

df3=df.groupby('smoker').sum()#用sum()函数计算不同顾客给的小费总和

df3['percent']=df3['tip']/df3['total_bill']*100#增加一列百分比数据

#哪一天哪种桌型给的小费最多或者比例最高?df4

df4=df.groupby(['day','size']).sum()#按照每天每桌来进行小费总和统计

df4['percent']=df4['tip']/df4['total_bill']*100#增加一列百分比数据

df4.dropna()#去除无数据的项

---------------------part 4数据可视化---------------------

sb.countplot(x='day',data=df)#按天进行小费统计并画图

plt.show()

sb.countplot(x='day',hue='size',data=df)#每天每种桌型的小费统计

plt.show()

sb.countplot(x='day',hue='smoker',data=df)#按顾客类型给的小费统计

plt.show()

下面给出各部分的运行结果。

--------------------part 2数据基本信息--------------------

df.head#前5项数据

df.info()#数据结构

数据类型、占用空间等

df.sample(5)#随机给出5组数据

df.describe()#数据统计

数据最大值、最小值等

----------------part 3数据分析 运行结果-----------------

#Tips数据分析,最累的一天,小费最多的情况(哪天,哪种顾客,哪种桌型)

#哪一天工作最累?df

df.groupby('day').count()#按day进行分组

#哪一天给的小费最多以及百分比最高?df2

df2=df.groupby('day').sum()#用sum()函数计算每天小费的总和(df2是一个数据表)

df2.drop('size',inplace=True,axis=1)# st去掉size项

df2['percent']=df2['tip']/df2['total_bill']*100#增加一列百分比数据(小费占总账单的百分比)

可以看到小费的比例占总账单的15%左右。

#哪种顾客给的小费最多?吸烟者还是非吸烟者?df3

df3=df.groupby('smoker').sum()#用sum()函数计算不同顾客给的小费总和

df3['percent']=df3['tip']/df3['total_bill']*100#增加一列百分比数据

#哪一天哪种桌型给的小费最多或者比例最高?df4(www.xing528.com)

df4=df.groupby(['day','size']).sum()#按照每天每桌来进行小费总和统计

df4['percent']=df4['tip']/df4['total_bill']*100#增加一列百分比数据

df4.dropna()#去除无数据的项

从这些数据分析的过程中,大家是不是发现了一些有趣的结论?其实在许多成功的商业案例中,都有基于观察(长时间的大数据)所采取的更有效的决策,例如商店的选址、客户定向广告的投放、商店货架商品的陈列方式等。观察后进行分析,发掘数据背后的小秘密!如果觉得数据表格有一点枯燥,下面我们采用可视化工具对数据以图的形式进行展示,这样可以得到更直观的感受。

----------------part 4数据可视化 运行结果----------------

sb.countplot(x='day',data=df)#按天进行小费统计并画图

plt.show()

sb.countplot(x='day',hue='smoker',data=df)#按顾客类型给的小费统计

plt.show()

sb.countplot(x='day',hue='size',data=df)#每天每种桌型的小费统计

plt.show()

从图形上我们也可以很快地得出以上结论,非吸烟者和更小的桌型支付的小费更多。

Tips建立模型

上面已经通过数据分析得到了一些结论,下面我们将建立一个模型,预测某种桌型某类客户在某天支付的小费金额。在建立模型之前,需要对数据进行一定的处理。在这个例子中,许多数据是文本数据,因此我们需要将其转换为数值型数据,例如男性为0,女性为1,非吸烟者为0,吸烟者为1,周四到周日分别为1,2,3,4。

---------------------part 5 数据预处理---------------------

#数据转换,使用update语句、replace方法,遍历所有的行和列,使用dummy变量(离散特征编码)

#将sex和smoker进行替换,男性为0,女性为1,非吸烟者为0,吸烟者为1

df.replace({'sex':{'Male':0,'Female':1},'smoker':{'No':0,'Yes':1}},inplace=True)

df.head()

#再将星期几进行离散化,例如有4天,就用4位离散数据来表示,第一位为1就表示属于这一类,因此周四到周日分别为1000,0100,0010,0001

days=pd.get_dummies(df['day'])

days.sample(5)

#数据清洗:如果想删除某些数据,例如某一天或者某种桌型的数据,可以采用drop()函数

days=pd.get_dummies(df['day'],drop_first=True)

days.sample(6)

#可以增加原有数据集的项数,利用concat()函数完成数据集的合并,其中参数axis=1表明在横轴方向增加数据,即增加列

days=pd.get_dummies(df['day'],drop_first=True)

df=pd.concat([df,days],axis=1)

times=pd.get_dummies(df['time'],drop_first=True)#将时间项进行离散化

df=pd.concat([df,times],axis=1)

df.drop(['day','time'],inplace=True,axis=1)#将原有的day和time项删除

df.head()

此时我们将原来的数据集df完全转换成纯数值型的数据表,便于后面进行建模

在对数据进行预处理之后,我们就可以建立模型并进行训练和预测了。在这里,我们只采用线性回归模型,数据集被分成训练集和测试集,这里没有采用校验集选择模型或者选择参数。

-------------------part 6 建立模型和预测-------------------

#确定输入特征向量X和输出特征向量Y

X=df[['sex','smoker','size','Fri','Sat','Sun',

'Dinner']]

Y=df[['tip']]

#数据集分配,将数据集分为训练集和预测集,调用train_test_split()函数,通过参数test_size 进行控制,0.25代表测试集占比为25%,random_state是一个随机数种子,不同的值随机划分的结果也不同

from sklearn.model_selection import train_test_split

from sklearn.linear_model import LinearRegression

X_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.25,random_state=26)

#模型训练,建立线性回归模型,调用LinearRegression()函数,采用model.fit进行训练

model=LinearRegression()

model.fit(X_train,y_train)

#模型预测,采用model.predict()函数

predictions=model.predict(X_test)

#画图比较,用预测值与实际值进行比较

bias=y_test-predictions #求取偏差值

sb.distplot(bias)

plt.show()

上图第一列表示账单的编号,第二列表示小费预测的偏差值。

小费偏差值的概率密度分布的直方图和核函数估计

上图为小费偏差值的概率密度分布的直方图和核函数估计(实线部分),可以看出,大部分的预测偏差还是很小的(在0附近图形达到峰值)。

接下来用已有的数据进行训练和测试。下面我们用已经建立好的模型对未来的情况做出预测,一个是周五午餐3人桌男性吸烟者,另一个是周日晚餐4人桌女性非吸烟者。X_train一共有7列,如:

对照各列的含义,给出这两组新数据的编码。其中sex=0表示男性,sex=1表示女性,smoker=1表示吸烟者,smoker=0表示非吸烟者,size=3表示为3人桌,size=4表示为4人桌,100表示周五,001表示周日,Dinner=0表示午餐,Dinner=1表示晚餐。因此第一组数据的编码为[0,1,3,1,0,0,0],第二组数据的编码为[1,0,4,0,0,1,1]。下面进行预测。

--------------------part 7 预测新数据--------------------

import numpy as np

myvals=np.array([0,1,3,1,0,0,0]).reshape(1,-1)#采用reshape()函数改变list的形状,1表示1行,-1表示若干列

model.predict(myvals)

这样可以预测出第一种情况可能获得的小费为3.12元。

myvals2=np.array([1,0,4,0,0,1,1]).reshape(1,-1)

model.predict(myvals2)

这样可以预测出第二种情况的预测结果为4.05元。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈