【火炉炼AI】机器学习018-项目案例:根据大楼进出人数预测是否举办活动

【火炉炼AI】机器学习018-项目案例:根据大楼进出人数预测是否举办活动

(本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

我们经常看到办公大楼中人来人往,进进出出,在平时没有什么活动的时候,进出大楼的人数会非常少,而一旦举办有大型商业活动,则人山人海,熙熙攘攘,所以很明显,大楼进出的人数和大楼是否举办活动有很明显的关联,那么,是否可以构建一个模型,通过大楼进出人数来预测该大楼是否在举办某种活动了?

答案是肯定的,且听炼丹老顽童娓娓道来。

1. 准备数据集

本项目案例所使用到的原始数据集来源于: UCI大学数据集,该数据集是公开的,读者可以自行下载该数据集到自己的本地电脑上。

1.1 了解数据集

从该数据集的官方网站上,我们可以看到该数据集的基本介绍:

可以看出,该数据集一共有10080个样本,没有缺失数据,一共有四个基本属性,集四个features,可以用于分类模型和时序模型,此处我们只是用来进行“是否举办活动”的预测,很明显,是一个多分类问题,具体而言是一个二分类问题。

在我们下载该数据后,通过查看比对,发现该有效数据主要存放在两个文件中(CalIt2.data和CalIt2.events),其中CalIt2.data中存储了10080条数据记录,每一条数据包含有四列,每一列的信息说明如下表所示。而CalIt2.events包括有30条数据记录,也包括有四列,其中的第一列是日期,第二列是活动开始时间,第三列是活动结束时间,第四列表示有活动。下是我总结的本项目案例数据集的基本信息。

其中表格中前面四行表示数据集的四个features,这些信息位于CalIt2.data中,最后一行表示数据集的Label,位于CalIt2.events中。

1.2 数据规整

由于本项目的数据集位于两个不同的文件中,同时两个文件的样本格式也不是一一对应,故而在构建模型之前,需要我们对数据进行规整,组成我们所需要的数据类型。

此处所用到的数据规整至少包括有三个方面:将同一个时间段内进出大楼的人数统一到一行,将CalIt2.events中的标记数据加载到CalIt2.data中组成完整的数据集,将数据集中的日期转换为星期数,作为一个特征向量。

1.2.1 进出大楼人员统一到一行

由于原始数据集CalIt2.data中,进大楼的位于一行,最前面的代号为9,出大楼的位于另外一行,最前面的代号为7,故而我们需要将这两行数据统一到一行,下面是实现代码,所采用的核心思想是:用DataFrame的布尔索引来获取进出大楼的单独一个DataFrame,然后将这两个DF整合到一个DataFrame中。

# 将feature_set中进楼和出楼的人员统计到一行。
# 目前数据集中出楼人员(代号7)位于偶数行,进楼人员(代号9)位于奇数行。
# 可以使用for in 方式依次取出各行的人员数,但此处我更愿意使用布尔型索引
code_7=feature_set[0]==7
code_7_data=feature_set[code_7].iloc[:,3].reset_index(drop=True)
code_9=feature_set[0]==9
code_9_data=feature_set[code_9].reset_index(drop=True)
# print(code_9_data)# OK
feature_set2=code_9_data
feature_set2[4]=code_7_data
feature_set2.drop([0],axis=1,inplace=True) # 删除第0列
# print(feature_set2) # col3 表示in,col4表示out,打印没有问题
# feature_set2.to_csv(‘d:/feature_set2.csv‘) # 保存以便查看是否有误

打印结果可以参考我的原始代码(我的github),此处由于打印出来后结果太长,我没有贴上来。

1.2.2 将label添加到Feature_set中组成完整的数据集

由于原始数据集的features特征向量放置在CalIt2.data文件中,且Label向量放置在CalIt2.events中,故而有必要将这两部分整合到一起。但是,整合过程并不是简单的将两个DataFrame连接起来,而要考虑时间范围。在CalIt2.events文件中列举了有活动的日期和起止时间,故而我们需要对Features中的日期和时间拿出来和CalIt2.events进行逐一比对,如果日期和时间落在events文件中,则表示这个时间段有活动,需要作出特殊标记。有很多种方法可以是实现这种逐一比对,下面我还是采用DataFrame的切片和索引来完成,我认为,这种方式算是速度比较快的一种方式。

# 下面是如何将feature_set2和label_set整合到一个DataFrame中来
# 要判断时间,如果feature_set2中的日期和时间都落在了label_set对应的时间内,
# 则表示有event发生,用1表示,如果没有,用0表示。
# 比较日期时间的方法有很多,此处我采用比较简单的方法
feature_set2[5]=0 # 表示是否有event的列都初始化为0

def calc_mins(time_str):
    nums=time_str.split(‘:‘)
    return 60*int(nums[0])+int(nums[1]) # 将时间转换为分钟数,此处不用考虑秒

for row_id,date in enumerate(label_set[0]): # 先取出label中的日期
    temp_df=feature_set2[feature_set2[1]==date]
    if temp_df is None:
        continue

    start_min=calc_mins(label_set.iloc[row_id,1])
    stop_min=calc_mins(label_set.iloc[row_id,2])
    for row in temp_df[2]: # 在逐一判断时间是否位于label中时间之间
        feature_min=calc_mins(row)
        if feature_min>=start_min and feature_min<=stop_min:
            feature_row=temp_df[temp_df[2]==row].index.tolist()
            feature_set2.loc[feature_row,5]=1 

# feature_set2.to_csv(‘d:/feature_set2_withLabel.csv‘) # 保存后打印查看没有问题   

1.2.3 将日期转换为星期数

这个相对于前面两个数据规整方面,要简单得多,直接贴代码。

# 进一步处理,由于日期在以后的日子里不可重复,作为feature并不合适,而可以用星期数来代替,
feature_set2[0]=pd.to_datetime(feature_set2[1])
# print(feature_set2.tail())
feature_set2[0]=feature_set2[0].map(lambda x: x.strftime(‘%w‘)) # 将日期转换为星期数
feature_set2=feature_set2.reindex(columns=range(6))
print(feature_set2.tail()) # 查看转换没有问题
feature_set2.to_csv(‘E:\PyProjects\DataSet\BuildingInOut/Sorted_Set.txt‘) # 将整理好的数据集保存,下次可以直接读取

-------------------------------------输---------出--------------------------------

0 1 2 3 4 5

5035 6 11/05/05 21:30:00 0 0 0

5036 6 11/05/05 22:00:00 0 3 0

5037 6 11/05/05 22:30:00 0 0 0

5038 6 11/05/05 23:00:00 0 0 0

5039 6 11/05/05 23:30:00 0 1 0

--------------------------------------------完-------------------------------------

处理完成之后的feature_set2可以直接保存一下,这样下次可以直接调用这个数据规整之后的文件,读取里面的数据集来训练和测试即可。

1.3 数据编码

很明显,从上面的数据集中可以看到第1列是日期,不适合做特征向量,需要删除,而第2列是字符串类型,没法用于机器学习,故而我们需要对第2列进行编码,如下代码:

# 由于第1列只是包含日期,作为特征向量并不合适,故而需要删除
feature_set2.drop([1],axis=1,inplace=True)
# 而第2列明显是字符串类型,里面的内容对机器学习而言如同天书,故需要编码
from sklearn import preprocessing
time_encoder=preprocessing.LabelEncoder()
feature_set2[2]=time_encoder.fit_transform(feature_set2[2])
print(feature_set2.tail())

-------------------------------------输---------出--------------------------------

0 2 3 4 5

5035 6 43 0 0 0

5036 6 44 0 3 0

5037 6 45 0 0 0

5038 6 46 0 0 0

5039 6 47 0 1 0

--------------------------------------------完-------------------------------------

所以,可以看到,第2列已经变成了数字编码,这部分内容在我以前的文章中用到过很多次。如【火炉炼AI】机器学习013-用朴素贝叶斯分类器估算个人收入阶层

########################小**********结###############################

1. 在网络上,我找了好久都没有找到如何处理这个数据集,好多都是直接给出处理后的结果,所以此处我就自己对这个数据集进行了规整,并将规整的代码放出来。

2. 数据集的规整和预处理往往会花掉机器学习的大部分时间,此处因为已经有了现成数据,仅仅是对数据进行规整,故而耗时相对较少。

3. Pandas和Numpy基本上是数据预处理,数据清洗,数据规整的有力神器,一定要熟练掌握。

#################################################################

2. 使用SVM构建分类器

SVM分类器的构建和其他项目案例中并没有太大差别,可以直接参考我的其他文章:【火炉炼AI】机器学习014-用SVM构建非线性分类模型.下面直接贴出代码。

# 下面是使用SVM构建分类器
from sklearn.svm import SVC
classifier=SVC(kernel=‘rbf‘,probability=True,class_weight=‘balanced‘)
classifier.fit(train_X,train_y)

-------------------------------------输---------出--------------------------------

SVC(C=1.0, cache_size=200, class_weight=‘balanced‘, coef0=0.0,

decision_function_shape=‘ovr‘, degree=3, gamma=‘auto‘, kernel=‘rbf‘,

max_iter=-1, probability=True, random_state=None, shrinking=True,

tol=0.001, verbose=False)

--------------------------------------------完-------------------------------------

# 用交叉验证来检验模型的准确性,只是在test set上验证准确性
from sklearn.cross_validation import cross_val_score
num_validations=5
accuracy=cross_val_score(classifier,test_X,test_y,
                         scoring=‘accuracy‘,cv=num_validations)
print(‘准确率:{:.2f}%‘.format(accuracy.mean()*100))
precision=cross_val_score(classifier,test_X,test_y,
                         scoring=‘precision_weighted‘,cv=num_validations)
print(‘精确度:{:.2f}%‘.format(precision.mean()*100))
recall=cross_val_score(classifier,test_X,test_y,
                         scoring=‘recall_weighted‘,cv=num_validations)
print(‘召回率:{:.2f}%‘.format(recall.mean()*100))
f1=cross_val_score(classifier,test_X,test_y,
                         scoring=‘f1_weighted‘,cv=num_validations)
print(‘F1  值:{:.2f}%‘.format(f1.mean()*100))

-------------------------------------输---------出--------------------------------

准确率:93.78%

精确度:92.96%

召回率:93.78%

F1 值:92.96%

--------------------------------------------完-------------------------------------

从交叉验证的结果可以看出,在测试集上,该SVM分类器仍然可以得到各项指标都达到90%以上的效果,可以认为,该SVM分类器的效果比较好。当然,如果还想继续提升该分类效果,可以使用GridSearch方法来搜索最佳参数组合,GridSearch的使用方法可以参考我的文章【火炉炼AI】机器学习017-使用GridSearch搜索最佳参数组合

3. 使用该分类器对新样本进行预测

首先我们需要新样本数据,此处我自己构建了一些新样本,并不一定准确,但是可以用于预测。对新样本的预测也很简单,直接使用classifier.predict()函数即可。

# 看起来该模型的预测效果很不错
# 那么用它来对新样本数据进行预测,会是什么样了?
new_samples=np.array([[2,‘09:30:00‘,20,12], # 即某个星期二,上午9点-9点半时间段,进大楼20人,出大楼12人
             [2,‘11:30:00‘,26,9],
             [6,‘12:30:00‘,4,22],
             [0,‘05:00:00‘,1,0]])
transformed=time_encoder.transform(new_samples[:,1])
# print(transformed) # 检查OK
new_samples[:,1]=transformed
print(new_samples)

# 使用classifier进行预测
output_class = classifier.predict(new_samples)
print(‘has events? {}‘.format(output_class))

-------------------------------------输---------出--------------------------------

[[‘2‘ ‘19‘ ‘20‘ ‘12‘]

[‘2‘ ‘23‘ ‘26‘ ‘9‘]

[‘6‘ ‘25‘ ‘4‘ ‘22‘]

[‘0‘ ‘10‘ ‘1‘ ‘0‘]]

has events? [0 1 0 0]

--------------------------------------------完-------------------------------------

从输出结果可以看出,只有第二个样本有活动,其他样本都没有活动,可以想象的出来,第一个样本9点-9点半有很多人进楼,但是少量人出楼,会不会是正常的上班族?而第二个样本11点到11点半之间有很多人进来,却很少有了出去,这个时间段应该就是会议期间正常的人员流动,而第三个样本12点到12点半,有很多人出楼,这大概是人家出去吃午饭吧。而第四个样本,周日的凌晨五点,估计只有鬼才能在大楼门口晃悠了。。。。

########################小**********结###############################

1. 这个项目的难点不在于SVM模型的构建和分类训练上,而在于前期数据集的规整上。

2. 后面使用SVM进行模型构建和训练,对新样本进行预测,在我前面的文章中讲了很多次了,至此已经没有什么新意了。

#################################################################

注:本部分代码已经全部上传到(我的github)上,欢迎下载。

参考资料:

1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

原文地址:https://www.cnblogs.com/RayDean/p/9765702.html

时间: 2024-10-09 04:42:23

【火炉炼AI】机器学习018-项目案例:根据大楼进出人数预测是否举办活动的相关文章

【火炉炼AI】机器学习019-项目案例:使用SVM回归器估算交通流量

[火炉炼AI]机器学习019-项目案例:使用SVM回归器估算交通流量 (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 我们都知道,SVM是一个很好地分类器,不仅适用于线性分类模型,而且还适用于非线性模型,但是,在另一方面,SVM不仅可以用于解决分类问题,还可以用于解决回归问题. 本项目打算使用SVM回归器来估算交通流量,所使用的方法和过程与我的上一篇文章[火炉炼AI]机器学习018-项

【火炉炼AI】机器学习006-用决策树回归器构建房价评估模型

[火炉炼AI]机器学习006-用决策树回归器构建房价评估模型 (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 最近几十年,房价一直是中国老百姓心中永远的痛,有人说,中国房价就像女人的无肩带文胸,一半人在疑惑:是什么支撑了它?另一半人在等待:什么时候掉下去? 而女人,永不可能让它掉下来.就算快掉下来了,提一提还是又上去了..... 虽然我们不能预测中国房价什么时候崩盘,但是却可以用机器学

【火炉炼AI】机器学习007-用随机森林构建共享单车需求预测模型

[火炉炼AI]机器学习007-用随机森林构建共享单车需求预测模型 (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 共享单车是最近几年才发展起来的一种便民交通工具,基本上是我等屌丝上班,下班,相亲,泡妞必备神器.本项目拟使用随机森林回归器构建共享单车需求预测模型,从而查看各种不同的条件下,共享单车的需求量. 1. 准备数据集 本次使用的数据集来源于加利福尼亚大学欧文分校(UCI)大学的公

【火炉炼AI】机器学习042-NLP文本的主题建模

[火炉炼AI]机器学习042-NLP文本的主题建模 (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, NLTK 3.3) 文本的主题建模时用NLP来识别文本文档中隐藏的某种模式的过程,可以发现该文档的隐藏主题,以便对文档进行分析.主题建模的实现过程是,识别出某文本文档中最有意义,最能表征主题的词来实现主题分类,即寻找文本文档中的关键词,通过关键词就可以识别出某文档的隐藏主题. 1. 准备数

【火炉炼AI】机器学习048-Harris检测图像角点

[火炉炼AI]机器学习048-Harris检测图像角点 (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 角点检测算法大致有三类:基于灰度图像的角点检测,基于二值图像的角点检测,基于轮廓曲线的角点检测.基于灰度图像的角点检测又可分为基于梯度.基于模板和基于模板梯度组合3类方法,其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点.常见的基

【火炉炼AI】机器学习017-使用GridSearch搜索最佳参数组合

[火炉炼AI]机器学习017-使用GridSearch搜索最佳参数组合 (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 在前面的文章([火炉炼AI]机器学习012-用随机森林构建汽车评估模型及模型的优化提升方法),我们使用了验证曲线来优化模型的超参数,但是使用验证曲线难以同时优化多个参数的取值,只能一个参数一个参数的优化,从而获取每个参数的最优值,但是有时候,一个非常优秀的模型,可能A

【火炉炼AI】机器学习046-图像边缘的检测方法

[火炉炼AI]机器学习046-图像边缘的检测方法 (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 图像中各种形状的检测时计算机视觉领域中非常常见的技术之一,特别是图像中直线的检测,圆的检测,图像边缘的检测等,下面我们来研究一下如何快速检测图像边缘. 边缘是不同区域的分界线,是周围(局部)像素有显著变化的像素的集合,有幅值与方向两个属性.这个不是绝对的定义,主要记住边缘是局部特征以及周围

【火炉炼AI】机器学习050-提取图像的Star特征

[火炉炼AI]机器学习050-提取图像的Star特征 (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 对于图像的特征点,前面我们讨论过边缘检测方法,Harris角点检测算法等,这些检测算法检测的都是图像的轮廓边缘,而不是内部细节,如果要进一步提取图像内部细节方面的特征,需要用到SIFT特征提取器和Star特征提取器.上一篇我们讲解了SIFT特征提取器,下面我们来介绍Star特征提取器.

【火炉炼AI】深度学习005-简单几行Keras代码解决二分类问题

[火炉炼AI]深度学习005-简单几行Keras代码解决二分类问题 (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, Keras 2.1.6, Tensorflow 1.9.0) 很多文章和教材都是用MNIST数据集作为深度学习届的"Hello World"程序,但是这个数据集有一个很大的特点:它是一个典型的多分类问题(一共有10个分类),在我们刚刚开始接触深度学习时,我倒是觉得