加载 sklearn 模型后无法进行预测
Unable to make prediction after loading sklearn model
我用 Scikit-Learn 创建了一个 ML 模型并保存了它。现在当我加载模型时,我在转换和预测方面遇到了麻烦。
我在 DataFrame 中有 4 个特征。前两个特征是文本的,另外两个是数字的。结果列为 1 或 0。
为了训练我的模型,我使用 ColumnTransformer
和 CountVectorizer
进行转换和矢量化文本特征。我指定了我想要 transform/vectorize 的列的名称。
(文本 1 和文本 2 列)。数值列不需要矢量化,因此 remainder='passthrough'
正在解决这个问题。
部分有效代码:
features = df.iloc[:, :-1]
results = df.iloc[:, -1]
transformerVectoriser = ColumnTransformer(transformers=[('vector word 1', CountVectorizer(analyzer='word', ngram_range=(1, 1), max_features = 12000, stop_words = 'english'), 'text1'),
('vector phrase 3', CountVectorizer(analyzer='word', ngram_range=(3, 3), max_features = 2500, stop_words = 'english'), 'text2')],
remainder='passthrough') # Default is to drop untransformed columns, passthrough == leave columns as they are
x_train, x_test, y_train, y_test = train_test_split(features, results, test_size=0.3, random_state=0)
x_train = transformerVectoriser.fit_transform(x_train)
x_test = transformerVectoriser.transform(x_test)
model = clf.fit(x_train, y_train)
y_pred = model.predict(x_test)
filename = 'ml_model.sav'
pickle.dump(model, open(filename, 'wb'))
filename = 'ml_transformer.sav'
pickle.dump(transformerVectoriser, open(filename, 'wb'))
但是当我想要加载模型并进行预测时,出现错误:
# LOADING MODEL
model = pickle.load(open('ml_model.sav','rb'))
vectorizer = pickle.load(open('ml_transformer.sav','rb'))
# MAKING PREDICTION
data_for_prediction = vectorizer.transform([data_for_prediction]) #ERROR
print(model.predict_proba(data_for_prediction))
我收到错误:
ValueError: Specifying the columns using strings is only supported for pandas DataFrames
当我训练我的模型时,我使用了 Pandas
数据框,当我想进行预测时,我只是将值放入列表中。所以 data_for_prediction
是列表,看起来像这样:
["text that should be vectorized with vectorizer that i created", "More texts that should be vectorized", 4, 7]
我认为那是错误,因为我在使用 ColumnTransformer 时使用了列名,但是现在当我要进行预测时,向量化器不知道要向量化什么。
我的最终模型和向量化器应该在 API 中使用,而 api 应该只使用 JSON,所以我不想将 JSON 转换为 DataFrame 并将其传递给模型。
有没有办法在我最终的 Flask APP 中不使用 pandas dataframe
来修复这个错误。
训练数据是一个包含以下列的数据框:
x_train.columns
函数vectorizer.transform()
需要相同格式的数据,所以假设
data_f_p = ["text that should be vectorized", 4,7,0]
对应于与x_train
相同的四列你可以用
把它变成一个dataframe
data_f_p = pd.DataFrame([data_f_p], columns=x_train.columns)
data_f_p = vectorizer.transform(data_f_p)
如果您不想在 REST API 端点中使用 pandas.DataFrame
,请不要使用 DataFrame
训练您的模型,而是将您的数据转换为numpy
数组优先:
>>> df
TEXT_1 TEXT_2 NUM_1 NUM_2
0 This is the first text. The second text. 300.000 23.3
1 Here is the third text. And the fourth text. 2.334 29.0
>>> df.to_numpy()
array([['This is the first text.', 'The second text.', 300.0, 23.3],
['Here is the third text.', 'And the fourth text.', 2.334, 29.0]],
dtype=object)
然后,更改您定义模型的方式。我建议使用 sklearn.pipeline.Pipeline
将预处理和预测步骤合并到一个模型中,如下所示:
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.ensemble import RandomForestClassifier
model = Pipeline(steps=[
('transformer', ColumnTransformer(
transformers=[
('TEXT_1', CountVectorizer(analyzer='word', stop_words='english'), 0),
('TEXT_2', CountVectorizer(analyzer='word', stop_words='english'), 1),
],
remainder='passthrough',
)),
('predictor', RandomForestClassifier()),
])
注意,这里我们在为 ColumnTransformer
实例定义转换器时使用索引而不是名称来引用文本。一旦我们将初始 DataFrame
转换为 numpy
数组,TEXT_1
特征位于 0
,TEXT_2
位于 1
在数据行中。以下是您可以如何使用该模型:
from joblib import dump, load
X = df.to_numpy()
model.fit(X, y)
dump(model, 'model.joblib')
...
model = load('model.joblib')
results = model.predict(data)
因此,您不必将传入数据转换为 DataFrame
即可进行预测。
我用 Scikit-Learn 创建了一个 ML 模型并保存了它。现在当我加载模型时,我在转换和预测方面遇到了麻烦。 我在 DataFrame 中有 4 个特征。前两个特征是文本的,另外两个是数字的。结果列为 1 或 0。
为了训练我的模型,我使用 ColumnTransformer
和 CountVectorizer
进行转换和矢量化文本特征。我指定了我想要 transform/vectorize 的列的名称。
(文本 1 和文本 2 列)。数值列不需要矢量化,因此 remainder='passthrough'
正在解决这个问题。
部分有效代码:
features = df.iloc[:, :-1]
results = df.iloc[:, -1]
transformerVectoriser = ColumnTransformer(transformers=[('vector word 1', CountVectorizer(analyzer='word', ngram_range=(1, 1), max_features = 12000, stop_words = 'english'), 'text1'),
('vector phrase 3', CountVectorizer(analyzer='word', ngram_range=(3, 3), max_features = 2500, stop_words = 'english'), 'text2')],
remainder='passthrough') # Default is to drop untransformed columns, passthrough == leave columns as they are
x_train, x_test, y_train, y_test = train_test_split(features, results, test_size=0.3, random_state=0)
x_train = transformerVectoriser.fit_transform(x_train)
x_test = transformerVectoriser.transform(x_test)
model = clf.fit(x_train, y_train)
y_pred = model.predict(x_test)
filename = 'ml_model.sav'
pickle.dump(model, open(filename, 'wb'))
filename = 'ml_transformer.sav'
pickle.dump(transformerVectoriser, open(filename, 'wb'))
但是当我想要加载模型并进行预测时,出现错误:
# LOADING MODEL
model = pickle.load(open('ml_model.sav','rb'))
vectorizer = pickle.load(open('ml_transformer.sav','rb'))
# MAKING PREDICTION
data_for_prediction = vectorizer.transform([data_for_prediction]) #ERROR
print(model.predict_proba(data_for_prediction))
我收到错误:
ValueError: Specifying the columns using strings is only supported for pandas DataFrames
当我训练我的模型时,我使用了 Pandas
数据框,当我想进行预测时,我只是将值放入列表中。所以 data_for_prediction
是列表,看起来像这样:
["text that should be vectorized with vectorizer that i created", "More texts that should be vectorized", 4, 7]
我认为那是错误,因为我在使用 ColumnTransformer 时使用了列名,但是现在当我要进行预测时,向量化器不知道要向量化什么。
我的最终模型和向量化器应该在 API 中使用,而 api 应该只使用 JSON,所以我不想将 JSON 转换为 DataFrame 并将其传递给模型。
有没有办法在我最终的 Flask APP 中不使用 pandas dataframe
来修复这个错误。
训练数据是一个包含以下列的数据框:
x_train.columns
函数vectorizer.transform()
需要相同格式的数据,所以假设
data_f_p = ["text that should be vectorized", 4,7,0]
对应于与x_train
相同的四列你可以用
data_f_p = pd.DataFrame([data_f_p], columns=x_train.columns)
data_f_p = vectorizer.transform(data_f_p)
如果您不想在 REST API 端点中使用 pandas.DataFrame
,请不要使用 DataFrame
训练您的模型,而是将您的数据转换为numpy
数组优先:
>>> df
TEXT_1 TEXT_2 NUM_1 NUM_2
0 This is the first text. The second text. 300.000 23.3
1 Here is the third text. And the fourth text. 2.334 29.0
>>> df.to_numpy()
array([['This is the first text.', 'The second text.', 300.0, 23.3],
['Here is the third text.', 'And the fourth text.', 2.334, 29.0]],
dtype=object)
然后,更改您定义模型的方式。我建议使用 sklearn.pipeline.Pipeline
将预处理和预测步骤合并到一个模型中,如下所示:
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.ensemble import RandomForestClassifier
model = Pipeline(steps=[
('transformer', ColumnTransformer(
transformers=[
('TEXT_1', CountVectorizer(analyzer='word', stop_words='english'), 0),
('TEXT_2', CountVectorizer(analyzer='word', stop_words='english'), 1),
],
remainder='passthrough',
)),
('predictor', RandomForestClassifier()),
])
注意,这里我们在为 ColumnTransformer
实例定义转换器时使用索引而不是名称来引用文本。一旦我们将初始 DataFrame
转换为 numpy
数组,TEXT_1
特征位于 0
,TEXT_2
位于 1
在数据行中。以下是您可以如何使用该模型:
from joblib import dump, load
X = df.to_numpy()
model.fit(X, y)
dump(model, 'model.joblib')
...
model = load('model.joblib')
results = model.predict(data)
因此,您不必将传入数据转换为 DataFrame
即可进行预测。