Scikit learn 自定义转换器维度不匹配

我来自R语言背景,所以scikit的API对我来说仍然很 confusing。我在按照这个教程 http://michelleful.github.io/code-blog/2015/06/20/pipelines/ 学习关于Pipelines的内容。所以让我们创建一个假数据集仅供参考:

x1,x2,yfoo,zoo,1bar,moo,2goo,too,3roo,zoo,4too,moo,5

我的目标非常简单:使用x1和x2的单独tfidf矩阵,加上从x1和x2中提取的一些自定义特征(例如,词长度等)来训练y的线性回归模型。

让我们从仅使用x1的tfidf开始这个较简单的任务。这里是完整的代码:

from sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import mean_squared_log_errorfrom sklearn.linear_model import LinearRegressionfrom sklearn.pipeline import Pipeline, FeatureUnionfrom sklearn.model_selection import KFoldfrom sklearn.model_selection import cross_val_scorefrom sklearn.metrics import fbeta_score, make_scorerfrom sklearn.base import BaseEstimator, TransformerMixinimport pandas as pdimport numpy as npimport timeimport reimport mathdef clip_RMSLE(y, y_pred, **kwargs):    y_pred[y_pred < 0] = 0.0    to_sum = [(math.log(y_pred[i] + 1) - math.log(y[i] + 1)) ** 2.0 for i,pred in enumerate(y_pred)]    return (sum(to_sum) * (1.0/len(y))) ** 0.5class ColumnNgram(BaseEstimator, TransformerMixin):    def __init__(self, colname, tokenizer, ngram_rg):        self.colname = colname        self.tokenizer = tokenizer        self.ngram_rg = ngram_rg        self.tfidf = None    def transform(self, df, y=None):         tfidf = TfidfVectorizer(tokenizer=self.tokenizer, ngram_range=self.ngram_rg)         return tfidf.fit_transform(df[self.colname].values)    def fit(self, df, y=None):        return selfstart = time.time()seed = 1991ngram_rg = (1,2)RMSLE = make_scorer(clip_RMSLE, greater_is_better=False)def tokenizer(text):    if text:        result = re.findall('[a-z]{2,}', text.lower())    else:        result = []    return resultdf = pd.read_csv('fake.csv', sep=',')y = df['y'].valuespipeline = Pipeline([('tfidf', ColumnNgram('x1', tokenizer, ngram_rg)),('linear_reg', LinearRegression(n_jobs=1))])kfold = KFold(n_splits=2, random_state=seed)results = cross_val_score(pipeline, df, y, cv=kfold, scoring=RMSLE)print(results)print(results.mean())end = time.time()print('Timeto finish this thing: %0.2fs' % (end - start))

我遇到了错误 ValueError: dimension mismatch,可能是因为某些术语不会同时出现在训练/验证折叠中。正确的做法是什么?谢谢!


回答:

将你的ColumnNgram改成这样:

class ColumnNgram(BaseEstimator, TransformerMixin):    def __init__(self, colname, tokenizer, ngram_rg):        self.colname = colname        self.tokenizer = tokenizer        self.ngram_rg = ngram_rg        self.tfidf = None    def transform(self, df, y=None):        return self.tfidf.transform(df[self.colname].values)    def fit(self, df, y=None):        self.tfidf = TfidfVectorizer(tokenizer=self.tokenizer, ngram_range=self.ngram_rg)        self.tfidf.fit(df[self.colname].values)        return self

你应该在fit()中声明并学习训练数据。目前你在每次调用transform()时都在重新拟合数据,这显然会导致训练和验证集中的特征不同,正如你所建议的。

正确的方法是保持一个TfidfVectorizer,它在fit()期间学习数据,然后在transform()中仅转换新数据,而不是重新拟合新数据。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注