Fli*_*lip 6 python numpy machine-learning pandas scikit-learn
我阅读了这篇关于scikit. 在OneHotEncoder服用串似乎是一个非常有用的功能。下面我尝试使用这个
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
cols = ['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_df = pd.read_csv('../../data/train.csv', usecols=cols)
test_df = pd.read_csv('../../data/test.csv', usecols=[e for e in cols if e != 'Survived'])
train_df.dropna(inplace=True)
test_df.dropna(inplace=True)
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test = test_df.copy()
ct = ColumnTransformer([("onehot", OneHotEncoder(sparse=False), ['Sex', 'Embarked'])], remainder='passthrough')
X_train_t = ct.fit_transform(train_df)
X_test_t  = ct.fit_transform(test_df)
print(X_train_t[0])
print(X_test_t[0])
# [ 0.    1.    0.    0.    1.    0.    3.   22.    1.    0.    7.25]
# [ 0.    1.    0.    1.    0.          3. 34.5     0.    0.  7.8292]
logreg = LogisticRegression(max_iter=5000)
logreg.fit(X_train_t, Y_train)
Y_pred = logreg.predict(X_test_t) # ValueError: X has 10 features per sample; expecting 11
acc_log = round(logreg.score(X_train, Y_train) * 100, 2)
print(acc_log)
我在使用此代码时遇到了以下 python 错误,并且还有一些其他问题。
ValueError:X 每个样本有 10 个特征;期待 11
从头开始……这个脚本是为 kaggle 的“泰坦尼克号”数据集编写的。我们有五个数值列Pclass,Age,SibSp,Parch和Fare。列Sex和Embarked是类别male/female和Q/S/C(这是城市名称的缩写)。
我从中了解到的OneHotEncoder是,它通过放置额外的列来创建虚拟变量。那么实际上输出ct.fit_transform()不再是熊猫数据帧,而是一个numpy数组。但正如在打印调试语句中看到的,现在有超过原来的 7 列。
我遇到了三个问题:
出于某种原因,test.csv它少了一列。这将向我表明其中一个类别的选项较少。为了解决这个问题,我必须在训练 + 测试数据的类别中找到所有可用的选项。然后使用这些选项(如男性/女性)分别对训练和测试数据进行变换。我不知道如何与我与(工作的工具,要做到这一点pandas,scikit等等)。再想一想..检查数据后,我在test.csv..中找不到丢失的选项。
我想避免“虚拟变量陷阱”。现在似乎创建了太多列。我期待 1 列性别(总选项 2 - 1 以避免陷阱)和 2 开始。加上额外的 5 个数字列,总数将达到 8 个。
我不再识别转换的输出。我更喜欢一个新的数据框,其中新的虚拟列给出了自己的名字,例如 Sex_male (1/0) Embarked_Q (1/0) 和 Embarked_S(1/0)
我只习惯于使用gretl,在那里虚拟化一个变量并忽略一个选项是很自然的。我不知道在 python 中我是否做错了或者这个场景是否不是标准 scikit 工具包的一部分。有什么建议吗?也许我应该为此编写一个自定义编码器?
Par*_*raj 11
我将尝试单独回答您的所有问题。
问题 1 的答案
在您的代码中,您fit_transform在火车和测试数据上都使用了方法,这不是正确的做法。通常,fit_transform仅应用于您的训练数据集,并返回一个转换器,然后将其用于transform您的测试数据集。当您应用fit_transform测试数据时,您只需使用仅在测试数据集中可用的分类变量的选项/级别来转换测试数据,并且您的测试数据很可能不包含所有选项/级别分类变量,因此您的训练和测试数据集的维度会有所不同,从而导致您得到的错误。
所以正确的做法是:
X_train_t = ct.fit_transform(X_train)
X_test_t  = ct.transform(X_test)
问题 2 的答案
如果您想避免“虚拟变量陷阱”,您可以在 中创建对象时使用参数drop(通过将其设置为first),这将导致只创建一列 for和两列 for因为它们有两个和三个选项/级别分别。OneHotEncoderColumnTransformersexEmbarked
所以正确的做法是:
ct = ColumnTransformer([("onehot", OneHotEncoder(sparse=False, drop="first"), ['Sex','Embarked'])], remainder='passthrough')
问题 3 的答案
截至目前get_feature_names,sklearn尚未实现可以使用新的虚拟列重建数据框的方法。一种解决方法是在构造中更改reminderto并单独构建数据框,如下所示:dropColumnTransformer
ct = ColumnTransformer([("onehot", OneHotEncoder(sparse=False, drop="first"), ['Sex', 'Embarked'])], remainder='drop')
A = pd.concat([X_train.drop(["Sex", "Embarked"], axis=1), pd.DataFrame(X_train_t, columns=ct.get_feature_names())], axis=1) 
A.head()
这将导致这样的事情:
您的最终代码将如下所示:
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
cols = ['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_df = pd.read_csv('train.csv', usecols=cols)
test_df = pd.read_csv('test.csv', usecols=[e for e in cols if e != 'Survived'])
cols = ['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_df = train_df.dropna()
test_df = test_df.dropna()
train_df = train_df.reset_index(drop=True)
test_df = test_df.reset_index(drop=True)
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test = test_df.copy()
categorical_values = ['Sex', 'Embarked']
X_train_cont = X_train.drop(categorical_values, axis=1)
X_test_cont = X_test.drop(categorical_values, axis=1)
ct = ColumnTransformer([("onehot", OneHotEncoder(sparse=False, drop="first"), categorical_values)], remainder='drop')
X_train_categorical = ct.fit_transform(X_train)
X_test_categorical  = ct.transform(X_test)
X_train_t = pd.concat([X_train_cont, pd.DataFrame(X_train_categorical, columns=ct.get_feature_names())], axis=1)
X_test_t = pd.concat([X_test_cont, pd.DataFrame(X_test_categorical, columns=ct.get_feature_names())], axis=1)
logreg = LogisticRegression(max_iter=5000)
logreg.fit(X_train_t, Y_train)
Y_pred = logreg.predict(X_test_t)
acc_log = round(logreg.score(X_train_t, Y_train) * 100, 2)
print(acc_log)
80.34
当X_train_t.head()你得到
希望这可以帮助!
| 归档时间: | 
 | 
| 查看次数: | 1638 次 | 
| 最近记录: |