我正在使用Pandas构建一个机器学习模型,但在将我的模型应用于用户输入的测试数据时遇到了困难。我的数据基本上是一个包含两列的dataframe:文本和情感。我希望能够预测用户输入的情感。这是我所做的:
1. 训练/测试模型
# 读取数据集df = pd.read_csv('dataset/dataset.tsv', sep='\t')# 分割训练/测试集test_size = 0.1train_x, valid_x, train_y, valid_y = model_selection.train_test_split(df['text'], df['sentiment'], test_size=test_size)# 对目标变量进行标签编码(即负面 = 0,正面 = 1)encoder = preprocessing.LabelEncoder()train_y = encoder.fit_transform(train_y)valid_y = encoder.fit_transform(valid_y)# 创建一个计数向量化对象count_vect = CountVectorizer(analyzer='word', token_pattern=r'\w{1,}')count_vect.fit(df['text'])# 使用计数向量化对象转换训练和验证数据xtrain_count = count_vect.transform(train_x)xvalid_count = count_vect.transform(valid_x)# 训练模型的函数def train_model(classifier, feature_vector_train, label, feature_vector_valid, name): # 在分类器上拟合训练数据集 classifier.fit(feature_vector_train, label) # 将训练好的模型保存到“models”文件夹中 joblib.dump(classifier, 'models/' + name + '.pkl') # 在验证数据集上预测标签 predictions = classifier.predict(feature_vector_valid) return metrics.accuracy_score(predictions, valid_y)# 使用计数向量的朴素贝叶斯accuracy = train_model(naive_bayes.MultinomialNB(), xtrain_count, train_y, xvalid_count, 'NB-COUNT')print("NB, Count Vectors: ", accuracy)
一切运行正常,准确率约为80%
2. 在用户输入上测试模型
然后我再次读取保存的模型,获取用户输入并尝试进行预测(用户输入目前在input_text
中是硬编码的):
clf = joblib.load('models/NB-COUNT.pkl')dataset_df = pd.read_csv('dataset/dataset.tsv', sep='\t')input_text = 'stackoverflow is the best' # 我想预测情感的句子test_df = pd.Series(data=input_text)count_vect = CountVectorizer(analyzer='word', token_pattern=r'\w{1,}')count_vect.fit(dataset_df['text']) # 再次拟合计数向量化器,以便我们可以从test_df中提取特征features = count_vect.transform(test_df)result = clf.predict(features)[0]print(result)
但我得到的错误是“维度不匹配”:
Traceback (most recent call last):File "C:\Users\vdvax\iCloudDrive\Freelance\09. Arabic Sentiment Analysis\test.py", line 20, in <module>result = clf.predict(features)[0]File "C:\Python36\lib\site-packages\sklearn\naive_bayes.py", line 66, in predictjll = self._joint_log_likelihood(X)File "C:\Python36\lib\site-packages\sklearn\naive_bayes.py", line 725, in _joint_log_likelihoodreturn (safe_sparse_dot(X, self.feature_log_prob_.T) +File "C:\Python36\lib\site-packages\sklearn\utils\extmath.py", line 135, in safe_sparse_dotret = a * bFile "C:\Python36\lib\site-packages\scipy\sparse\base.py", line 515, in __mul__raise ValueError('dimension mismatch')ValueError: dimension mismatch
回答:
您得到维度不匹配的错误是因为CountVectorizer
转换的输出与拟合估算器中预期的形状在维度上不匹配。这是由于您在测试数据上拟合了一个单独的CountVectorizer
造成的。
Scikit-learn提供了一个名为Pipeline
的方便接口,它允许您将预处理器和估算器堆叠在一个单一的估算器类中。您应该在您的估算器之前将所有变换器放入Pipeline
中,然后您的测试数据将由预拟合的变换器类进行转换。以下是您可以如何拟合一个管道版本的估算器:
from sklearn.pipeline import Pipeline# 接受一个元组列表,其中第一个参数是步骤名称,# 第二个参数是估算器本身。pipe = Pipeline([ ('cvec', CountVectorizer(analyzer='word', token_pattern=r'\w{1,}')), ('clf', naive_bayes.MultinomialNB())])# 您可以像拟合任何其他估算器一样拟合管道,# 它将按顺序通过每个阶段pipe.fit(train_x, train_y)# 您可以通过将测试数据输入管道来产生预测pipe.predict(test_x)
请注意,这样做您不必创建多个阶段预处理的多个数据副本,因为一个阶段的输出会直接输入到下一个阶段。
现在,对于您的持久化问题。管道可以像其他模型一样被持久化:
joblib.dump(pipe, 'models/NB-COUNT.pkl')loaded_model = joblib.load('models/NB-COUNT.pkl')loaded_model.predict(test_df)