我正在尝试解决Kaggle上的泰坦尼克生存问题。这是我在实际学习机器学习的第一步。我遇到一个问题,性别列会导致错误。堆栈跟踪显示 could not convert string to float: 'female'
。你们是如何遇到这个问题的?我不想要解决方案。我只想知道处理这个问题的实际方法,因为我确实需要性别列来构建我的模型。
这是我的代码:
import pandas as pdfrom sklearn.tree import DecisionTreeRegressorfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import mean_absolute_errortrain_path = "C:\\Users\\Omar\\Downloads\\Titanic Data\\train.csv"train_data = pd.read_csv(train_path)columns_of_interest = ['Survived','Pclass', 'Sex', 'Age']filtered_titanic_data = train_data.dropna(axis=0)x = filtered_titanic_data[columns_of_interest]y = filtered_titanic_data.Survivedtrain_x, val_x, train_y, val_y = train_test_split(x, y, random_state=0)titanic_model = DecisionTreeRegressor()titanic_model.fit(train_x, train_y)val_predictions = titanic_model.predict(val_x)print(filtered_titanic_data)
回答:
处理这个问题有几种方法,具体取决于你的需求:
- 你可以将你的类别编码为数值,即将每个类别的级别转换为不同的数字,
或者
- 虚拟编码你的类别,即将每个类别的级别转换为单独的列,并赋予
0
或1
的值。
在许多机器学习应用中,处理因子时使用虚拟编码更好。
请注意,对于只有两个级别的类别,按照下面概述的方法进行数值编码本质上与虚拟编码是等价的:所有不是级别0
的值必然是级别1
。实际上,在我下面给出的虚拟编码示例中,存在冗余信息,因为我为两个类别各设了一列。这只是为了说明概念。通常情况下,只会创建n-1
列,其中n
是级别的数量,省略的级别是隐含的(即,创建一个Female
列,所有0
的值隐含为Male
)。
将类别编码为数值:
方法1:pd.factorize
pd.factorize
是一种简单快速的数值编码方法:
例如,如果你的gender
列看起来像这样:
>>> df gender0 Female1 Male2 Male3 Male4 Female5 Female6 Male7 Female8 Female9 Femaledf['gender_factor'] = pd.factorize(df.gender)[0]>>> df gender gender_factor0 Female 01 Male 12 Male 13 Male 14 Female 05 Female 06 Male 17 Female 08 Female 09 Female 0
方法2:categorical
数据类型
另一种方法是使用category
数据类型:
df['gender_factor'] = df['gender'].astype('category').cat.codes
这将得到相同的结果
方法3 sklearn.preprocessing.LabelEncoder()
这种方法带有一些额外的好处,比如容易进行反向转换:
from sklearn import preprocessingle = preprocessing.LabelEncoder()# 转换性别列df['gender_factor'] = le.fit_transform(df.gender)>>> df gender gender_factor0 Female 01 Male 12 Male 13 Male 14 Female 05 Female 06 Male 17 Female 08 Female 09 Female 0# 容易进行反向转换:df['gender_factor'] = le.inverse_transform(df.gender_factor)>>> df gender gender_factor0 Female Female1 Male Male2 Male Male3 Male Male4 Female Female5 Female Female6 Male Male7 Female Female8 Female Female9 Female Female
虚拟编码:
方法1:pd.get_dummies
df.join(pd.get_dummies(df.gender)) gender Female Male0 Female 1 01 Male 0 12 Male 0 13 Male 0 14 Female 1 05 Female 1 06 Male 0 17 Female 1 08 Female 1 09 Female 1 0
注意,如果你想省略一列以获得非冗余的虚拟编码(见本回答开头的说明),你可以使用:
df.join(pd.get_dummies(df.gender, drop_first=True)) gender Male0 Female 01 Male 12 Male 13 Male 14 Female 05 Female 06 Male 17 Female 08 Female 09 Female 0