前导
更多文章代码详情可查看博主个人网站:https://www.iwtmbtly.com/
下文用到的数据集和代码可以从这里下载《数据集》
机器学习是一种从数据生成规则、发现模型,来帮助我们预测、判断、分析和解决问题的技术。
一个机器学习项目从开始到结束大致分为5步,分别是定义问题、收集数据和预处理、选择算法和确定模型、训练拟合模型、评估并优化模型性能。这5步是一个循环迭代的过程,可以参考下面的图片:
所有的项目都会按照这5步来做,我把它简称为实战5步。为了让你更深地理解这5步,在后面能更快地上手,我会带你做一个项目,我会给你清楚解释每一个步骤的目的和背后的原理。首先我们先来一起搞定前两步,也就是定义问题和数据的预处理。
第一步:定义问题
我们先来看第一步,定义问题。在定义问题这个环节中,我们要剖析业务场景,设定清晰的目标,同时还要明确当前问题属于哪一种机器学习类型。如果不搞清楚这些,我们后面就无法选择模型了。
所以首先,我们先得来了解一下我们这个项目的业务场景。假设你已经入职了“易速鲜花”的运营部,正在对微信公众号推广文案的运营效率进行分析。你收集了大量的软文数据,包括点赞数、转发数和浏览量等等,就像下面这样:
因为微信公众号阅读量超过10万之后,就不能显示它的具体阅读量了。所以针对这个问题,我们项目的目标就是,建立一个机器学习模型,根据点赞数和转发数等指标,估计一篇文章能实现多大的浏览量。
因为要估计浏览量,所以在这个数据集中:点赞数、转发数、热度指数、文章评级,这4个字段都是特征,浏览量就是标签。这里我们已经有要估计的标签了,所以这是一个监督学习问题。再加上我们的标签是连续性的数值,因此它是一个回归问题。
不难看出,在这个数据集中,特征和标签之间明显呈现出一种相关性:点赞数、转发数多的时候,往往浏览量也多。但是,这种相关性可以通过哪个具体的函数来描绘呢?目前我们还不知道,所以我们在这个项目中的任务就是找到这个函数。
第二步:收集数据和预处理
“数据的收集和预处理”在所有机器学习项目中都会出现,它的作用是为机器学习模型提供好的燃料。数据好,模型才跑得更带劲。这步骤看似只有一句话,其实里面包含了好几个小步骤,完整来讲有6步:
- 收集数据;
- 数据可视化;
- 数据清洗;
- 特征工程;
- 构建特征集和标签集;
- 拆分训练集、验证集和测试集。
你可能一眼看上去不太明白这6个步骤的意思。不要着急,接下来我会继续结合“易速鲜花”这个项目挨个解释的。
(一)收集数据
首先是收集数据,这一步又叫采集数据。在我们的项目中,我已经把它做好了,你可以在这里下载现成的数据集。
不过,在现实中,收集数据通常很辛苦,要在运营环节做很多数据埋点、获取用户消费等行为信息和兴趣偏好信息,有时候还需要上网爬取数据。
有了数据集,接下来我们要做的是数据可视化的工作,也就是通过可视化去观察一下数据,为选择具体的机器学习模型找找感觉。
(二)数据可视化
数据可视化是个万金油技能,能做的事非常多。比如说,可以看一看特征和标签之间可能存在的关系,也可以看看数据里有没有“脏数据”和“离群点”等。如果想要深入学习数据可视化,推荐可以看这篇文章《一次学会Python数据可视化》。
不过在正式可视化之前,我们需要把收集到的数据导入运行环境。数据导入我们需要用到Pandas数据处理工具包。这个包可是操作数据的利器,我们未来每个项目中都会用到。现在我们用import语句导入它,然后,我们通过下面的代码把这个项目的数据集读入到Python运行环境,用DataFrame的形式呈现出来::
importpandasaspd # 导入Pandas数据处理工具包
df_ads=pd.read_csv('.\data\易速鲜花微信软文.csv') # 读入数据
df_ads.head() # 显示前几行数据
DataFrame是机器学习中常见的二维表格类型数据结构。在上面的代码中,我用read_csv()
API把CSV格式的数据文件,读入到Pandas的DataFrame中,把它命名为了df_ads。这段代码输出如下:
这样就完成了数据的导入了,接着我们就可以正式进入“可视化”了。根据经验,我们猜测“点赞数”最有可能和“浏览量”之间存在线性关系。那是不是真的这样呢?我们可以画出图来验证一下。
在这个“验证”环节中,我们需要用到两个包:一个是Python画图工具库“Matplotlib”,另一个是统计学数据可视化工具库“Seaborn”。这两个包都是Python数据可视化的必备工具包,它们是Anaconda默认安装包的一部分,不需要pip install
语句重复安装。
在导入这两个包时,我们依旧用import语句。请你注意,为了节省代码量,也是为了加快运行速度,我并没有导入完整的matplotlib包,而是只导入了matplotlib包中的绘图模块pyplot,因为线性关系可以简单地用散点图来验证一下。所以下面我们用matplotlib包中的plot()
API,绘制出“点赞数”和“浏览量”之间的散点图,看看它们的分布状态:
# 导入数据可视化所需要的库
importmatplotlib.pyplotasplt # Matplotlib–Python画图工具库
importseabornassns # Seaborn–统计学数据可视化工具库
# 方法一
plt.figure(dpi=500) # 设置图形的清晰度
plt.plot(df_ads['点赞数'],df_ads['浏览量'],'r.',label='Trainingdata') # 用matplotlib画图
plt.xlabel('点赞数') # x轴Label
plt.ylabel('浏览量') # y轴Label
plt.legend() # 显示图例
plt.show() # 显示绘图结果
# 方法二
plt.figure(dpi=500) # 设置图形的清晰度
plt.scatter(df_ads['点赞数'],df_ads['浏览量'],marker='o')
plt.xlabel('点赞数') # x轴Label
plt.ylabel('浏览量') # y轴Label
plt.show()
输出的结果如下图所示:
从这张图中我们可以看出来,这些数据基本上集中在一条线附近,所以它的标签和特征之间,好像真的存在着线性的关系,这可以为我们将来选模型提供参考信息。
接下来,我要用Seaborn的boxplot工具画个箱线图。来看看这个数据集里有没有“离群点”。我这里随便选择了热度指数这个特征,你也可以为其它特征试试绘制箱线图。
importpandasaspd
importmatplotlib.pyplotasplt
importseabornassns
# 用seaborn画箱线图
plt.figure(dpi=500) # 设置图形的清晰度
data=pd.concat([df_ads['浏览量'],df_ads['热度指数']],axis=1) # 浏览量和热度指数
fig=sns.boxplot(x='热度指数',y="浏览量",data=data) # 用seaborn的箱线图画图
fig.axis(ymin=0,ymax=800000); # 设定y轴坐标
下图就是输出的箱线图:
箱线图是由五个数值点组成,分别是最小值(min)、下四分位数(Q1)、中位数(median)、上四分位数(Q3)和最大值(max)。在统计学上,这叫做五数概括。这五个数值可以清楚地为我们展示数据的分布和离散程度。
这个图中下四分位数、中位数、上四分位数组成一个“带有隔间的盒子”,就是所谓的箱;上四分位数到最大值之间建立一条延伸线,就是所谓的线,也叫“胡须”;胡须的两极就是最小值与最大值;此外,箱线图还会将离群的数据点单独绘出。
在上面这个箱线图中,我们不难发现,热度指数越高,浏览量的中位数越大。我们还可以看到,有一些离群的数据点,比其它的文章浏览量大了很多,这些“离群点”就是我们说的“爆款文章”了。
到这里,数据可视化工作算是基本完成了。在数据可视化之后,下一步就是数据的清洗。
(三)数据清洗
很多人都把数据清洗比作“炒菜”前的“洗菜”,也就是说数据越干净,模型的效果也就越好。清洗的数据一般分为4种情况:
-
第一种是处理缺失的数据:如果备份系统里面有缺了的数据,那我们尽量补录;如果没有,我们可以剔除掉残缺的数据,也可以用其他数据记录的平均值、随机值或者0值来补值。这个补值的过程叫数据修复。
-
第二个是处理重复的数据:如果是完全相同的重复数据处理,删掉就行了。可如果同一个主键出现两行不同的数据,比如同一个身份证号后面有两条不同的地址,我们就要看看有没有其他辅助的信息可以帮助我们判断(如时戳),要是无法判断的话,只能随机删除或者全部保留。
-
第三个是处理错误的数据:比如商品的销售量、销售金额出现负值,这时候就需要删除或者转成有意义的正值。再比如表示百分比或概率的字段,如果值大于1,也属于逻辑错误数据。
-
第四个是处理不可用的数据:这指的是整理数据的格式,比如有些商品以人民币为单位,有些以美元为单位,就需要先统一。另一个常见例子是把“是”、“否”转换成“1”、“0”值再输入机器学习模型。
那么如何看数据集中有没有脏数据呢?
就我们这个项目的数据集来说,细心的你可能在DataFrame图中已经发现,行索引为6的数据中“转发数”的值是“NaN”,意思是NotANumber。在Python中,它代表无法表示、也无法处理的值。这是典型的脏数据。
我们可以通过DataFrame的isna().sum()
函数来统计所有的NaN的个数。这样,我们就可以在看看有没有NaN的同时,也看看NaN出现的次数。如果NaN过多的话,那么说明这个数据集质量不好,就要找找数据源出了什么问题。
df_ads.isna().sum() # NaN出现的次数
输出结果如下:
点赞数0
转发数37
热度指数0
文章评级0
浏览量0
dtype:int64
输出显示我们的数据集中“转发数”这个字段有37个NaN值。对于上千条数据的数据集,这还不算很多。那么该如何处理呢?也很简单。我们可以用dropna()
这个API把出现了NaN的数据行删掉。
df_ads=df_ads.dropna() # 把出现了NaN的数据行删掉
你可能会觉得,我们刚才通过箱线图找到了离群点(爆款文章),这些算是脏数据吗?这是个很好的问题,而且这个问题并没有固定的答案。
删去了离群点,模型针对普通的数据会拟合得比较漂亮。但是现实生活中,就是存在着这样的离群点,让模型不那么漂亮。如果把这里的离群点删掉,那模型就不能工作得那么好了。所以,这是一个平衡和取舍的过程。
我们可以训练出包含这些离群点的模型,以及不包含这些离群点的模型,并进行比较。在这里,我建议保留这些“离群点”。
现在,我们就完成了对这个数据的简单清洗。
(四)特征工程
特征工程是一个专门的机器学习子领域,而且我认为它是数据处理过程中最有创造力的环节,特征工程做得好不好,非常影响机器学习模型的效率。
我举个例子来解释下什么是特征工程。你知道什么是BMI指数吗?它等于体重除以身高的平方,这就是一个特征工程。
什么意思呢?就是说经过了这个过程,BMI这一个指数就替代了原来的两个特征——体重和身高,而且完全能客观地描绘我们的身材情况。
因此,经过了这个特征工程,我们可以把BIM指数作为新特征,输入用于评估健康情况的机器学习模型。
你可能会问这样做的好处是什么?以BMI特征工程为例,它降低了特征数据集的维度。维度就是数据集特征的个数。要知道,在数据集中,每多一个特征,模型拟合时的特征空间就更大,运算量也就更大。所以,摒弃掉冗余的特征、降低特征的维度,能使机器学习模型训练得更快。
这只是特征工程的诸多的妙处之一,此外特征工程还能更好地表示业务逻辑,并提升机器学习模型的性能。
由于我们这个项目的问题相对简单,对特征工程的要求并不高,这里暂时不做特征工程。
(五)构建特征集和标签集
我们说过,特征就是所收集的各个数据点,是要输入机器学习模型的变量。而标签是要预测、判断或者分类的内容。对于所有监督学习算法,我们都需要向模型中输入“特征集”和“标签集”这两组数据。因此,在开始机器学习的模型搭建之前,我们需要先构建一个特征数据集和一个标签数据集。
具体的构建过程也很简单,我们只要从原始数据集删除我们不需要的数据就行了。在这个项目中,特征是点赞数、转发数、热度指数和文章评级,所以只需要从原始数据集中删除“浏览量”就行了。
X=df_ads.drop(['浏览量'],axis=1) # 特征集,Drop掉标签相关字段
而标签是我们想要预测的浏览量,因此,我们在标签数据集中只保留“浏览量”字段:
y=df_ads.浏览量 # 标签集
下面我们再看看特征集和标签集里面都有什么数据。
X.head() # 显示前几行数据
y.head() # 显示前几行数据
因为Notebook一个单元格只能有一个输出。实际操作需要把显示两个数据的代码放在了不同的单元格中。它们的输出结果如下图所示:
可以看到,除了浏览量之外,所有其它字段仍然都在特征数据集中,而只有浏览量被保存在了标签数据集中,也就是说原始数据集就被拆分成了机器学习的特征集和标签集。
无监督学习算法是不需要这个步骤的,因为无监督算法没有标签。
不过,从原数据集从列的维度纵向地拆分成了特征集和标签集后,还需要进一步从行的维度横向拆分。
因为机器学习并不是通过训练数据集找出一个模型就结束了,我们需要用验证数据集看看这个模型好不好,然后用测试数据集看看模型在新数据上能不能用。
(六)拆分训练集、验证集和测试集
在拆分之前,我先说明一点,对于学习型项目来说,为了简化流程,经常会省略验证的环节。我们今天的项目比较简单,所以我们也省略了验证,只拆分训练集和测试集,而此时的测试集就肩负着验证和测试双重功能了。
拆分的时候,留作测试的数据比例一般是20%或30%。不过如果你的数据量非常庞大,比如超过1百万的时候,那你也不一定非要留这么多。一般来说有上万条的测试数据就足够了。这里我会按照80/20的比例来拆分数据。具体的拆分,我们会用机器学习工具包scikit-learn里的数据集拆分工具train_test_split
来完成:
# 将数据集进行80%(训练集)和20%(验证集)的分割
fromsklearn.model_selectionimporttrain_test_split # 导入train_test_split工具
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=0)
这里请你注意一下,虽然是随机分割,但我们要指定一个random_state值,这样就保证程序每次运行都分割一样的训练集和测试集。训练集和测试集每次拆分都不一样的话,那比较模型调参前后的优劣就失去了固定的标准。
现在,训练集和测试集拆分也完成了,你会发现原始数据现在变成了四个数据集,分别是:
- 特征训练集(X_train)
- 特征测试集(X_test)
- 标签训练集(y_train)
- 标签测试集(y_test)
现在我们完成了,定义问题以及数据的收集和预处理。不明确定义要解决的问题,我们就没办法有的放矢地选择模型。
而数据的收集和预处理虽然看起来没有模型的选择和优化那么“吸引眼球”,但它其实才是机器学习项目成败的关键。这一步可以分为下图中的6个小步:
这6步中,尤其是数据可视化和特征工程,因为无定法可循,所以很考验经验,它既是我们对着已有数据找感觉的过程,又是下一步把数据“喂”给模型之前的必要准备。
除此之外,还有两点需要注意:
-
第一点是,这些子步骤中的次序并不是固定的,比如数据可视化和特征工程,很多时候是先可视化,发现了一些特征工程的思路,然后做特征工程,然后再次可视化。而且有的特征工程比如特征缩放,还必须在拆分数据之后做;
-
第二点,这些子步骤在一个特定的机器学习项目中,可能不需要全部用到。比如说无监督学习项目,就不需要创建特征集和标签集这个步骤,一般也不需要用到验证集和测试集。
第三步:选择算法并建立模型
在这一步中,我们需要先根据特征和标签之间的关系,选出一个合适的算法,并找到与之对应的合适的算法包,然后通过调用这个算法包来建立模型。
选算法的过程很考验数据科学家们的经验,具体到我们这个项目里,从上文中可以知道,我们这个数据集里的某些特征和标签之间,存在着近似线性的关系。而且,这个数据集的标签是连续变量,因此,适合用回归分析来寻找从特征到标签的预测函数。
所谓回归分析(regressionanalysis),就是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析,说白了就是当自变量变化的时候,研究一下因变量是怎么跟着变化的,它可以用来预测客流量、降雨量、销售量等。
不过,回归分析的算法有很多种,比如说线性回归,多项式回归,贝叶斯回归等等,那具体该选哪个呢?其实,这是根据特征和标签之间的关系来决定的。
在前面的可视化过程中,我们推测特征和标签可能存在线性关系,并且用散点图简单做了验证。所以这里,我们就选择用线性回归算法来建模。
线性回归算法是最简单、最基础的机器学习算法,它其实就是给每一个特征变量找参数的过程。我想你一定熟悉一元线性回归的公式:
对于一元线性回归来说,它的内部参数就是未知的斜率和截距。只不过在机器学习中,我们把斜率a叫做权重(weight),用英文字母w代表,把截距b叫做偏置(bias),用英文字母b代表。所以机器学习中一元线性回归的公式也写成:
而在我们这个项目中,数据集中有4个特征,所以就是:
因此,我们的模型就会有5个内部参数,也就是4个特征的权重和一个偏置(截距)需要确定。不过这些公式的具体代码实现,都不用我们自己完成,它们全部封装在工具包里了。你只要对算法的原理有个印象就行了。
确定好算法后,我们接着来看一下调用什么样的算法包建立模型比较合适。
对于机器学习来说,最常用的算法工具包是scikit-learn,简称sklearn,它是使用最广泛的开源Python机器学习库,堪称机器学习神器。sklearn提供了大量用于数据挖掘的机器学习工具,覆盖数据预处理、可视化、交叉验证和多种机器学习算法。
虽然我们已经选定使用线性回归算法,但是在sklearn中又有很多线性回归算法包,比如说基本的线性回归算法LinearRegression,以及在它的基础上衍生出来的Lasso回归和Ridge回归等。
那哪一个才是适合我们这个项目的算法包呢?其实,我们一般选算法包的方法是从能够解决该问题的最简单的算法开始尝试,直到得到满意的结果为止。对于这个项目,我们选择LinearRegression,它也是机器学习中最常见、最基础的回归算法包。其它回归算法包,未来我会慢慢给你介绍。
调用LinearRegression建立模型非常简单,两行代码就可以搞定:
fromsklearn.linear_modelimportLinearRegression # 导入线性回归算法模型
# 类似于创建一个Python类
linereg_model=LinearRegression() # 使用线性回归算法创建模型
可以看到,我把这个线性回归模型命名为了“linereg_model”。那到这里,我们算不算是建立好模型了呢?是的,模型已经创建出来了,我们可以开始训练它了。不过,有一点需要指出,建立模型时,你通常还需要了解它有哪些外部参数,同时指定好它的外部参数的值。
模型的参数有两种:内部参数和外部参数。内部参数是属于算法本身的一部分,不用我们人工来确定,刚才提到的权重w和截距b,都是线性回归模型的内部参数;而外部参数也叫做超参数,它们的值是在创建模型时由我们自己设定的。
对于LinearRegression模型来讲,它的外部参数主要包括两个布尔值:
- fit_intercept,默认值为True,代表是否计算模型的截距。
- normalize,默认值为False,代表是否对特征X在回归之前做规范化。
不过呢,对于比较简单的模型来说,默认的外部参数设置也都是不错的选择,所以,我们不显式指定外部参数而直接调用模型,也是可以的。在上面的代码中,我就是在创建模型时直接使用了外部参数的默认值。
第四步:训练模型
训练模型就是用训练集中的特征变量和已知标签,根据当前样本的损失大小来逐渐拟合函数,确定最优的内部参数,最后完成模型。虽然看起来挺复杂,但这些步骤,我们都通过调用fit方法来完成。
fit方法是机器学习的核心环节,里面封装了很多具体的机器学习核心算法,我们只需要把特征训练数据集和标签训练数据集,同时作为参数传进fit方法就行了。
linereg_model.fit(X_train,y_train) # 用训练集数据,训练机器,拟合函数,确定内部参数
运行该语句后的输出如下:
LinearRegression()
这样,我们就完成了对模型的训练。你可能会觉得很奇怪,既然训练模型是机器学习的核心环节,怎么只有一句代码?其实这就是我反复强调过的,由于优秀的机器学习库的存在,我们可以用一两行语句实现很强大的功能。所以,不要小看上面那个简单的fit语句,这是模型进行自我学习的关键过程。
在这个过程里,fit的核心就是减少损失,使函数对特征到标签的模拟越来越贴切。那么它具体是怎么减少损失呢?这里我画了一张图片展示模型从很不靠谱到比较靠谱的过程。
这个拟合的过程,同时也是机器学习算法优化其内部参数的过程。而优化参数的关键就是减小损失。
那什么是损失呢?它其实是对糟糕预测的惩罚,同时也是对模型好坏的度量。损失也就是模型的误差,也称为成本或代价。名字虽多,但都是一个意思,就是当前预测值和真实值之间的差距的体现。它是一个数值,表示对于单个样本而言模型预测的准确程度。如果模型的预测完全准确,则损失为0;如果不准确,就有损失。
在机器学习中,我们追求的当然是比较小的损失。不过,模型好不好,还不能仅看单个样本,还要针对所有数据样本,找到一组平均损失“较小”的函数模型。样本的损失大小,从几何意义上基本可以理解为预测值和真值之间的几何距离。平均距离越大,说明误差越大,模型越离谱。在下面这个图中,左边是平均损失较大的模型,右边是平均损失较小的模型,模型所有数据点的平均损失很明显大过右边模型。
因此,针对每一组不同的参数,机器都会基于样本数据集,用损失函数算一次平均损失。而机器学习的最优化过程,就是逐步减小训练集上损失的过程。具体到我们今天这个回归模型的拟合,它的关键环节就是通过梯度下降,逐步优化模型的参数,使训练集误差值达到最小。这也就是我们刚才讲的那个fit语句所要实现的最优化过程。
因此,针对每一组不同的参数,机器都会基于样本数据集,用损失函数算一次平均损失。而机器学习的最优化过程,就是逐步减小训练集上损失的过程。具体到我们今天这个回归模型的拟合,它的关键环节就是通过梯度下降,逐步优化模型的参数,使训练集误差值达到最小。这也就是我们刚才讲的那个fit语句所要实现的最优化过程。
在这里面,线性回归中计算误差的方法很好理解,就是数据集中真值与预测值之间的残差平方和。那梯度下降又是怎么一回事呢?为了让你直观地理解,我用一张图来展示一下,梯度下降是怎么一步一步地走到损失曲线中的最小损失点的。
就像图里这样,梯度下降其实就和下山一样。你可以想象一下,当你站在高处,你的目标就是找到一系列的参数,让训练数据集上的损失值最小。那么你该往哪走才能保证损失值最小呢?关键就是通过求导的方法,找到每一步的方向,确保总是往更小的损失方向前进。
所以,你可以看出方向是有多么的重要。机器学习最优化之所以能够拟合出最佳的模型,就是因为能够找到前进方向,你看,不仅我们人需要方向,连AI也需要正确的方向。
那到这里为止,我们已经完成了模型的建立和训练,接下来,一起看看怎么对这个训练好的模型进行评估和优化,让它尽可能精准地估计出文章浏览量。
第五步:模型的评估和优化
我们刚才说,梯度下降是在用训练集拟合模型时最小化误差,这时候算法调整的是模型的内部参数。而在验证集或者测试集进行模型效果评估的过程中,我们则是通过最小化误差来实现超参数(模型外部参数)的优化。
对此,机器学习工具包(如scikit-learn)中都会提供常用的工具和指标,对验证集和测试集进行评估,进而计算当前的误差。比如R方或者MSE均方误差指标,就可以用于评估回归分析模型的优劣。
不过呢,在开始评估模型之前,我想请你思考一下:在我们这5个实战步骤里面,并没有“使用模型预测浏览量”这个环节,这是为什么呢?其实这个环节已经包含在第5步“模型性能的评估和优化”之中了,并且是我们在第5步中首先要去实现的。
具体来说,在“模型的评估和优化”这一步中,当我们预测完测试集的浏览量后,我们要再拿这个预测结果去和测试集已有的真值去比较,这样才能够求出模型的性能。而这整个过程也同样是一个循环迭代的过程,我把这个循环过程总结成了下面的图,你可以看看:
对于这个项目来说,预测测试集的浏览量,只需要用训练好的模型linereg_model中的predict方法,在X_test(特征测试集)上进行预测,这个方法就会返回对测试集的预测结果。
y_pred=linereg_model.predict(X_test)#预测测试集的Y值
在几乎所有的机器学习项目中,你都可以用predict方法来进行预测,它就是用模型在任意的同类型数据集上去预测真值的,可以应用于验证集、测试集,当然也可以应用于训练集本身。
这里我要说明一下,为了简化流程,我们并没有真正进行验证和测试的多重循环。因此,在这个项目中,X_test既充当了测试集,也充当了验证集。
拿到预测结果后,我们再通过下面的代码,把测试数据集的原始特征数据、原始标签真值,以及模型对标签的预测值组合在一起进行显示、比较。
df_ads_pred=X_test.copy() # 预测集特征数据
df_ads_pred['浏览量真值']=y_test # 测试集标签真值
df_ads_pred['浏览量预测值']=y_pred # 测试集标签预测值
df_ads_pred # 显示数据
输出如下结果:
可以看出,浏览量预测值是比较接近于真值的。而且对于一些文章,这个模型的预测得非常准确,比如编号第145号数据,其实际浏览量为119501,预测浏览量为110710。这就是一个很棒的结果。
如果你想看看现在的模型长得什么样?你可以通过LinearRegression的coef_和intercept_属性打印出各个特征的权重和模型的偏置来。它们也就是模型的内部参数。
print("当前模型的4个特征的权重分别是:",linereg_model.coef_)
print("'当前模型的截距(偏置)是:",linereg_model.intercept_)
输入如下:
当前模型的4个特征的权重分别是:[48.0839522434.7306222929730.133124892949.62196343]
当前模型的截距(偏置)是:-127493.90606857173
这也就是说,我们现在的模型的线性回归公式是:
y=48.08x1(点赞)+34.73x2(转发)+29730.13x3(热度)+2949.62x4(评级)−127493.91
不过到这里,整个机器学习项目并没有结束,我们最后还要给出当前这个模型的评估分数:
print("线性回归预测评分",linereg_model.score(X_test,y_test))#评估模型
在机器学习中,常用于评估回归分析模型的指标有两种:R方分数和MSE指标,并且大多数机器学习工具包中都会提供相关的工具。对此,你无需做过多了解,只需要知道我们这里的score这个API中,选用的是R方分数来评估模型的就可以了。
最后我们得到这样的结果:
线性回归预测评分0.740552064611524
可以看到,R方值约为0.74。那这意味着什么呢?
一般来说,R方的取值在0到1之间,R方越大,说明所拟合的回归模型越优。现在我们得到的R方值约为0.74,在没有与其它模型进行比较之前,我们实际上也没法确定它是否能令人满意。
因为分数的高低,与数据集预测的难易程度、模型的类型和参数都有关系。而且,R方分数也不是线性回归模型唯一的评估标准。
不过你需要知道的是,如果模型的评估分数不理想,我们就需要回到第3步,调整模型的外部参数,重新训练模型。要是得到的结果依旧不理想,那我们就要考虑选择其他算法,创建全新的模型了。如果很不幸,新模型的效果还是不好的话,我们就得回到第2步,看看是不是数据出了问题。
这也是为什么,我一直强调机器学习项目是一个循环迭代的过程,优秀的模型都是一次次迭代的产物。
当模型通过了评估,就可以去解决实际问题了,机器学习项目也算是基本结束。
总结
我们通过一个预测软文浏览量的实战项目,了解了机器学习项目要经历5个步骤。第一步就是通过定义问题来明确我们的项目目标;第二步是数据的收集和预处理,这一步的重点是把数据转换成机器学习可处理的格式,这样我们就可以在第三步中针对问题选定适宜的算法,来建立模型了。
有了模型后,我们要在接下来的第四步中训练模型、拟合函数。最后,再对训练好的模型进行评估和优化。对于这最后一步,也就是第5步,我们的重点是反复测评,找到最优的超参数,确定最终模型。
近期评论