使用sklearn进行UCI machine learning数据集的机器学习实战

数据背景

本实验使用的数据集来自 UCI machine learning 数据集生命科学类中的Localization Data for Person Activity Data Set,以下为数据集的官方网址:http://archive.ics.uci.edu/ml/datasets/Localization+Data+for+Person+Activity?tdsourcetag=s_pctim_aiomsg

此数据集共有164860个样本以及8个特征,样本数×特征数 > 50万,包含了五个人的左右脚踝、腰部和胸部在不同时间点的位置坐标等属性,根据这些属性,将受试者分为行走、躺下、站立等11种不同的行为状态。

数据概况

以下是数据集的基本属性介绍:

1
2
3
4
5
6
7
8
9
10
SequenceName:{A01,A02,A03,A04,A05,B01,B02,B03,B04,B05,C01,C02,C03,C04,C05,D01,D02,D03,D04,D05,E01,E02,E03,E04,E05} (Nominal) 
- A, B, C, D, E = 5 people

TagIdentificator:代表人体的不同部位,分为ANKLE_LEFT、ANKLE_RIGHT、CHEST、BELT
Timestamp:时间戳
date FORMAT:符合 dd.MM.yyyy HH:mm:ss:SSS 形式的日期数据
x:x坐标
y:y坐标
z:z坐标
activity:共有以下11种行为状态:{walking, falling, lying down, lying, sitting down, sitting, standing up from lying, on all fours, sitting on the ground, standing up from sitting, standing up from sitting on the ground}

首先读入数据,并观察数据集的前五行数据,以及数据集的基本信息:

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd

path = "./ConfLongDemo_JSI.txt"
df = pd.read_table(path, sep=',')

df.head()
df.info()

观察到 Timestamp 和 date FORMAT 都为时间数据,存在强相关的冗余,因此可将 date FORMAT 属性去除,只对Timestamp进行分析。

数据预处理

挑选出类别型特征(SequenceName, TagIdentificator),将其转换为哑变量:

1
2
3
4
5
6
7
# 对类别型特征进行哑变量的制作
cat_features = ['SequenceName', 'TagIdentificator']
for col in cat_features:
df[col] = df[col].astype('object')
X_cat = df[cat_features]
X_cat = pd.get_dummies(X_cat)
print(X_cat.head())

挑选出数值型特征(Timestamp,x,y,z),进行数据的标准化和归一化。标准化(Z-Score)的公式为:(X-mean)/std 计算时对每个属性/每列分别进行,使用sklearn.preprocessing.scale()函数,可以直接将给定数据进行标准化。标准化的目的在于避免原始特征值差异过大,导致训练得到的参数权重不归一,无法比较各特征的重要性。在数据标准化之后进行数据的归一化,查看结果的前五行:

1
2
3
4
5
6
7
# 对数值型特征进行数据标准化和归一化
scale_X = StandardScaler()
num_features = ['Timestamp', 'x', 'y', 'z']
X_num = scale_X.fit_transform(df[num_features])
X_num = normalize(X_num, norm='l2')
X_num = pd.DataFrame(data=X_num, columns=num_features, index=df.index)
print(X_num.head())

在分别对数值型数据已经类别型数据进行数据预处理后,将它们合并组成X和y,并确定结果的维度:

1
2
3
4
5
6
# 合并数据
X = pd.concat([X_cat, X_num], axis=1, ignore_index=False)
y = df['activity']
print(X.head())
print(X.shape)
print(y.shape)

将数据预处理部分封装为函数,以下是数据预处理的函数代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 数据预处理
def preprocessing():
# 对类别型特征进行哑变量的制作
cat_features = ['SequenceName', 'TagIdentificator']
for col in cat_features:
df[col] = df[col].astype('object')
X_cat = df[cat_features]
X_cat = pd.get_dummies(X_cat)
print(X_cat.head())

# 对数值型特征进行数据标准化和归一化
scale_X = StandardScaler()
num_features = ['Timestamp', 'x', 'y', 'z']
X_num = scale_X.fit_transform(df[num_features])
X_num = normalize(X_num, norm='l2')
X_num = pd.DataFrame(data=X_num, columns=num_features, index=df.index)
print(X_num.head())

# 合并数据
X = pd.concat([X_cat, X_num], axis=1, ignore_index=False)
y = df['activity']
print(X.head())
print(X.shape)
print(y.shape)

return X, y

算法训练与评估

在训练数据前,首先制作训练数据集和测试数据集,使用sklearn的train_test_split()函数,划分训练集:测试集 = 8:2并随机打乱,然后查看训练集和测试集的维度:

1
2
3
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0, test_size=0.20, shuffle=True)
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)
1
2
(131888, 33) (131888,)
(32972, 33) (32972,)

共使用9种算法进行训练,从而选取出最适合的算法,分别是K近邻算法、决策树算法、先验为高斯分布的朴素贝叶斯算法、支持向量机算法、KNN Bagging算法、Tree Bagging算法、随机森林算法、adaboost算法、GBDT算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
clfs = {'K_neighbor': neighbors.KNeighborsClassifier(),
'decision_tree': tree.DecisionTreeClassifier(),
'naive_gaussian': naive_bayes.GaussianNB(),
'svm': svm.SVC(),
'bagging_knn': BaggingClassifier(neighbors.KNeighborsClassifier(), max_samples=0.5,max_features=0.5),
'bagging_tree': BaggingClassifier(tree.DecisionTreeClassifier(), max_samples=0.5,max_features=0.5),
'random_forest': RandomForestClassifier(n_estimators=50),
'adaboost': AdaBoostClassifier(n_estimators=50),
'gradient_boost': GradientBoostingClassifier(n_estimators=50, learning_rate=1.0,max_depth=1, random_state=0)
}

for clf_key in clfs.keys():
print('\nthe classifier is:', clf_key)
clf = clfs[clf_key]

begin = time.clock()
clf.fit(X_train, y_train.ravel())
elapsed = time.clock() - begin

score = clf.score(X_test, y_test.ravel())
print('the score is:', score)
print('the elapsed is:', elapsed)

结果与讨论

对于每一个模型也同时计算了模型的准确度以及算法的时间消耗,具体每个模型的结果如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
the classifier is: bagging_knn
the score is: 0.6743600630838287
the elapsed is: 16.453809

the classifier is: svm
the score is: 0.5400642969792552
the elapsed is: 1674.055688

the classifier is: naive_gaussian
the score is: 0.15222006551012982
the elapsed is: 0.30271300000003976

the classifier is: gradient_boost
the score is: 0.03709207812689555
the elapsed is: 45.588802000000214

the classifier is: random_forest
the score is: 0.7794492296493994
the elapsed is: 12.297873000000209

the classifier is: adaboost
the score is: 0.35078248210602936
the elapsed is: 19.544486999999663

the classifier is: decision_tree
the score is: 0.7021412107242508
the elapsed is: 1.9036650000002737

the classifier is: K_neighbor
the score is: 0.7600994783452627
the elapsed is: 1.0251819999998588

可以看到,机器学习模型的复杂度并不直接与准确度成正比。在独立测试集中,最简单的KNN模型能达到0.789的准确度,而adaboost、gradient_boost等集成方法却连0.4的准确度都达不到。在这9种算法中,准确度最高的是三个算法是决策树、Bagging Tree 和随机森林,都达到了0.85以上,看来树模型很适合这个数据集。因此,模型直接没有优劣之分,只有适不适合的说法,具体用什么方法还是得取决于具体的问题。

参考

https://www.zhangshenghai.com/posts/28687/
https://blog.csdn.net/xiao_lxl/article/details/95978015
https://blog.csdn.net/MYCSDN6666/article/details/80849158
https://blog.csdn.net/Dream_angel_Z/article/details/49406573
http://archive.ics.uci.edu/ml/datasets/Localization+Data+for+Person+Activity?tdsourcetag=s_pctim_aiomsg