一、分析目的
(1)分析泰坦尼克号数据集,说明每个属性的类别;
(2)将幸存属性设置为类别标签,使用K近邻算法作为分类算法(无需考虑PassengerID,name,ticket和cabin,去掉带缺失属性的样本),在测试集上预测乘客的幸存情况并计算准确率。
二、分析属性类别
使用pd.read_csv读入train.csv。打印data_train.info()以及data_train的所有列,如下图所示。
由图一可知,Age, Cabin, Embarked属性有缺失;PassengerId, Survived, Pclass, SibSp, Parch为int类型;Age, Fare为float类型;Name, Sex, Ticket, Cabin, Embarked为object类型,即string类型。
由图二进一步分析可知各个属性的类别:PassengerId, Name, Ticket, Cabin, Embarked为标称属性,代表的是事物的名称或一些符号;Survived和Sex为二元属性,Survived仅有两个取值0/1,Sex仅有两个取值male/female,且Survived为非对称二元属性,Sex为对称二元属性;Pclass为序数属性,取值1、2、3表示不同的社会地位;Age, SibSp, Parch, Fare为数值属性,均为可度量的量。
三、K近邻算法分类
1. 去除相关属性,删去缺失值,设置标签,将Sex和Embarked属性由str属性编码为int,便于进一步计算混合属性距离。完成相关处理后打印数据集如下图所示:
相关代码如下所示:
data_train = data_train.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1)
data_train = data_train.dropna()
data_train['Survived'] = data_train['Survived'].astype('category')
label_encoder = LabelEncoder()
data_train['Sex'] = label_encoder.fit_transform(data_train['Sex'])
data_train['Embarked'] = label_encoder.fit_transform(data_train['Embarked'])
print(data_train)
2. 划分训练集
使用train_test_split将训练集划出30%作为测试集。打印划分后的训练集测试集信息如下:
(训练集信息)
(测试集信息)
可以看出按照7:3划分了训练集和测试集。相关代码如下所示:
X = data_train.drop('Survived', axis=1)
y = data_train['Survived']
# print(X)
# print(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=33)
print(X_train.info())
print(X_test.info())
3. 自定义混合距离函数
按照定义对数值属性、标称属性/二元属性、序数属性进行相应处理,最后用公式求平均值,得出mixed_distance。
1)序数属性
先转换为数值属性再计算相异性,转换后的取值范围为[0, 1.0]。
2)标称属性/二元属性
比较两个对象的该属性值是否相等,相等距离为0,不相等距离为1。
3)数值属性
先找出各个属性在数据集上的最大值和最小值,按照的公式计算距离。
完整函数实现代码如下所示:
age_max = data_train['Age'].max()
age_min = data_train['Age'].min()
sibsp_max = data_train['SibSp'].max()
sibsp_min = data_train['SibSp'].min()
parch_max = data_train['Parch'].max()
parch_min = data_train['Parch'].min()
fare_max = data_train['Fare'].max()
fare_min = data_train['Fare'].min()
def mixed_distance(x1, x2):
# 序数属性Pclass
x1[0] = (x1[0] - 1) / (3.0 - 1) # 转换成数值属性
x2[0] = (x2[0] - 1) / (3.0 - 1)
pclass_distance = abs(x1[0] - x2[0]) / (1.0 - 0)
# Sex(二元),Embarked(标称)
# 看x1,x2的'Sex'和'Embarked'值是否相等,相等距离为 0,不相等距离为 1
sex_distance = 0 if x1[1] == x2[1] else 1
embarked_distance = 0 if x1[6] == x2[6] else 1
# 数值属性:Age,SibSp,Parch,Fare
age_distance = abs(x1[2] - x2[2]) / (age_max - age_min)
sib_distance = abs(x1[3] - x2[3]) / (sibsp_max - sibsp_min)
parch_distance = abs(x1[4] - x2[4]) / (parch_max - parch_min)
fare_distance = abs(x1[5] - x2[5]) / (fare_max - fare_min)
distance = 1 / 7 * (
pclass_distance + sex_distance + embarked_distance + age_distance + sib_distance + parch_distance + fare_distance)
return distance
4. 交叉验证
使用5折交叉验证,选择最优的k,使用cross_val_score函数进行K折交叉验证。在使用KNeighborsClassifier时设置参数metric=mixed_distance。打印出最优的k,结果如下:
相关代码如下所示:
k_values = list(range(1, 21))
kfold = KFold(n_splits=10, shuffle=True, random_state=22)
cv_scores = []
for k in k_values:
knn = KNeighborsClassifier(n_neighbors=k, metric=mixed_distance)
scores = cross_val_score(knn, X_train, y_train, cv=kfold, scoring='accuracy')
cv_scores.append(scores. Mean())
best_k = k_values[cv_scores.index(max(cv_scores))]
print("best_k is:",best_k)
5. KNN模型训练及测试
设置KNeighborsClassifier的参数n_neighbors=best_k, metric=mixed_distance。打印准确率:
相关代码如下所示:
knn = KNeighborsClassifier(n_neighbors=best_k, metric=mixed_distance)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
test_accuracy = accuracy_score(y_test, y_pred)
print(test_accuracy)
四、结论与总结
1. 各个属性的类型:
2. 混合类型属性集的相异性量度需要分三个部分考虑。
序数属性:
先转换为数值属性再计算相异性,转换后的取值范围为[0, 1.0]。
标称属性/二元属性:
比较两个对象的该属性值是否相等,相等距离为0,不相等距离为1。
数值属性:
先找出各个属性在数据集上的最大值和最小值,按照的公式计算距离。
最后对所有距离求平均得到混合属性距离。