SOK*_*SOK 4 python scikit-learn
我有一个运行以下命令的模型:
import pandas as pd
import numpy as np
# initialize list of lists
data = [['tom', 10,1,'a'], ['tom', 15,5,'a'], ['tom', 14,1,'a'], ['tom', 15,4,'b'], ['tom', 18,1,'b'], ['tom', 15,6,'a'], ['tom', 17,3,'a']
, ['tom', 14,7,'b'], ['tom',16 ,6,'a'], ['tom', 22,2,'a'],['matt', 10,1,'c'], ['matt', 15,5,'b'], ['matt', 14,1,'b'], ['matt', 15,4,'a'], ['matt', 18,1,'a'], ['matt', 15,6,'a'], ['matt', 17,3,'a']
, ['matt', 14,7,'c'], ['matt',16 ,6,'b'], ['matt', 10,2,'b']]
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['Name', 'Attempts','Score','Category'])
print(df.head(2))
Name Attempts Score Category
0 tom 10 1 a
1 tom 15 5 a
Run Code Online (Sandbox Code Playgroud)
然后我使用以下代码创建了一个虚拟 df 以在模型中使用:
from sklearn.linear_model import LogisticRegression
df_dum = pd.get_dummies(df)
print(df_dum.head(2))
Attempts Score Name_matt Name_tom Category_a Category_b Category_c
0 10 1 0 1 1 0 0
1 15 5 0 1 1 0 0
Run Code Online (Sandbox Code Playgroud)
然后我创建了以下模型:
#Model
X = df_dum.drop(('Score'),axis=1)
y = df_dum['Score'].values
#Training Size
train_size = int(X.shape[0]*.7)
X_train = X[:train_size]
X_test = X[train_size:]
y_train = y[:train_size]
y_test = y[train_size:]
#Fit Model
model = LogisticRegression(max_iter=1000)
model.fit(X_train,y_train)
#Send predictions back to dataframe
Z = model.predict(X_test)
zz = model.predict_proba(X_test)
df.loc[train_size:,'predictions']=Z
dfpredictions = df.dropna(subset=['predictions'])
print(dfpredictions)
Name Attempts Score Category predictions
14 matt 18 1 a 1.0
15 matt 15 6 a 1.0
16 matt 17 3 a 1.0
17 matt 14 7 c 1.0
18 matt 16 6 b 1.0
19 matt 10 2 b 1.0
Run Code Online (Sandbox Code Playgroud)
现在我有了我想要预测的新数据:
newdata = [['tom', 10,'a'], ['tom', 15,'a'], ['tom', 14,'a']]
newdf = pd.DataFrame(newdata, columns = ['Name', 'Attempts','Category'])
print(newdf)
Name Attempts Category
0 tom 10 a
1 tom 15 a
2 tom 14 a
Run Code Online (Sandbox Code Playgroud)
然后创建虚拟对象并运行预测
newpredict = pd.get_dummies(newdf)
predict = model.predict(newpredict)
Run Code Online (Sandbox Code Playgroud)
输出:
ValueError: X has 3 features per sample; expecting 6
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为没有类别b,c也没有名为 的名称matt。
我的问题是,鉴于我的新数据并不总是具有原始数据中使用的完整列集,因此设置此模型的最佳方法是什么。每天我都有新数据,所以我不太确定最有效且无错误的方法。
这是一个示例数据 - 我的数据集在运行时有 2000 列pd.get_dummies。非常感谢!
让我更详细地解释 Nicolas 和 BlueSkyz 的建议。
\n\npd.get_dummies当您确定生产/新数据集中的特定分类变量不会有任何新类别(例如,基于您公司或数据库的内部数据分类/一致性规则的性别、产品等)时,此功能非常有用。
然而,对于大多数机器学习任务来说,未来可能会出现模型训练中未使用的新类别,这sklearn.OneHotEncoder应该是标准选择。handle_unknown的参数sklearn.OneHotEncoder可以设置为\'ignore\'做到这一点:将来应用编码器时忽略新类别。从文档中:
\n\n\n如果转换期间存在未知分类特征,是否引发错误或忽略(默认为引发)。当此参数设置为 \xe2\x80\x98ignore\xe2\x80\x99 且在转换过程中遇到未知类别时,该功能生成的 one-hot 编码列将全为零。在逆变换中,未知类别将表示为 None
\n
基于 LabelEncoding 和 OneHotEncoding 的示例的完整流程如下:
\n\n# Create a categorical boolean mask\ncategorical_feature_mask = df.dtypes == object\n# Filter out the categorical columns into a list for easy reference later on in case you have more than a couple categorical columns\ncategorical_cols = df.columns[categorical_feature_mask].tolist()\n\n# Instantiate the OneHotEncoder Object\nfrom sklearn.preprocessing import OneHotEncoder\nohe = OneHotEncoder(handle_unknown=\'ignore\', sparse = False)\n# Apply ohe on data\nohe.fit(df[categorical_cols])\ncat_ohe = ohe.transform(df[categorical_cols])\n\n#Create a Pandas DataFrame of the hot encoded column\nohe_df = pd.DataFrame(cat_ohe, columns = ohe.get_feature_names(input_features = categorical_cols))\n#concat with original data and drop original columns\ndf_ohe = pd.concat([df, ohe_df], axis=1).drop(columns = categorical_cols, axis=1)\n\n# The following code is for your newdf after training and testing on original df\n# Apply ohe on newdf\ncat_ohe_new = ohe.transform(newdf[categorical_cols])\n#Create a Pandas DataFrame of the hot encoded column\nohe_df_new = pd.DataFrame(cat_ohe_new, columns = ohe.get_feature_names(input_features = categorical_cols))\n#concat with original data and drop original columns\ndf_ohe_new = pd.concat([newdf, ohe_df_new], axis=1).drop(columns = categorical_cols, axis=1)\n\n# predict on df_ohe_new\npredict = model.predict(df_ohe_new)\nRun Code Online (Sandbox Code Playgroud)\n\n输出(您可以将其分配回 newdf):
\n\narray([1, 1, 1])\nRun Code Online (Sandbox Code Playgroud)\n\n但是,如果您确实只想使用pd.get_dummies,那么以下方法也可以:
newpredict = newpredict.reindex(labels = df_dum.columns, axis = 1, fill_value = 0).drop(columns = [\'Score\'])\npredict = model.predict(newpredict)\nRun Code Online (Sandbox Code Playgroud)\n\n上面的代码片段将确保您的新虚拟 df (newpredict) 中具有与原始 df_dum (带有0值)相同的列,并删除该\'Score\'列。这里的输出与上面相同。此代码将确保新数据集中存在但现在原始训练数据中存在的任何分类值都将被删除,同时保持列的顺序与原始 df 中的顺序相同。
编辑:\n我忘记添加的一件事是pd.get_dummies执行速度通常比sklearn.OneHotEncoder