我在尝试Quora不诚实问题分类竞赛(延迟提交),但遇到了一个奇怪的错误,我无法解决。这里是我的代码(相关部分):
def loss(predict, observed): a = predict*observed b = predict+observed return 2*(a/b)train = pd.read_csv('../input/train.csv')test = pd.read_csv('../input/test.csv')train = train.iloc[0:5000, :]test = test.iloc[0:1000, :]qid = test['qid']train = train.drop('qid', axis=1)test = test.drop('qid', axis=1)x_train, x_val, y_train, y_val = train_test_split(train['question_text'], train['target'])count = CountVectorizer(stop_words='english', ngram_range=(1,1), min_df=1, #tokenizer=LemmaTokenizer() )tfidf = TfidfVectorizer(stop_words='english', ngram_range=(1,1), min_df=1, #tokenizer=LemmaTokenizer() )count.fit(list(x_train), list(x_val))x_train_count = count.transform(x_train)x_val_count = count.transform(x_val)logistic = LogisticRegression()logistic.fit(x_train_count, y_train)predictions = logistic.predict_proba(x_val_count)print("loss: %0.3f " %loss(predictions, y_val))
当我运行它时,我得到了这个错误:
ValueError: operands could not be broadcast together with shapes (1250,2) (1250,)
我知道为什么会得到这个错误:因为我不能直接乘以两个数组。但这里有一些尺寸看起来不合理:
x_val_count.shape - (1250, 8411)
我假设这是评论的扩展数组(1250个测试样本),以数字形式显示。但打印的数组开头是这样的:
(0, 1057) 1 (0, 4920) 1 (0, 5563) 1 (1, 2894) 1 (1, 3403) 1 (2, 3311) 1 (3, 1386) 1 (3, 1646) 1 (4, 3207) 1 (4, 3330) 1 (4, 6111) 1 (5, 2346) 1 (5, 4148) 1 (5, 4441) 1 (5, 5223) 1 (5, 5316) 1 (5, 5378) 1 (5, 5565) 2 (5, 7571) 1 (6, 746) 2 (6, 983) 1 (6, 985) 1 (6, 3182) 1 (6, 3455) 1 (6, 4636) 1
这看起来只有两列。为什么会有这种差异?
predictions.shape - (1250, 2)
我不知道为什么预测有两列。为什么不是一列?
我希望如果我了解更多,我将能够解决这个问题。但有人知道我如何修复这个问题吗?
回答:
这里有几个问题,所以我将尝试逐一回答它们。
x_val_count.shape - (1250, 8411)
表示有1250个样本和8411个特征(其中8411是您的词汇量大小)。然而,出于效率原因,scikit-learn的向量化器以稀疏矩阵的形式存储数据(非零特征的索引)。这是因为特征列中有很多0(一份文档 – 在您的案例中是一个Quora问题 – 几乎不会包含词汇表中1%的词)。如果您想将其转换为常规矩阵,您可以简单地调用 x_val_count.toarray()
,然而,您可能会因为这将是一个巨大的矩阵而耗尽内存。输出
(0, 1057) 1(0, 4920) 1(0, 5563) 1
可以解释为“文档0中有3个词,每个词出现一次。” 如果您想知道这些词是什么,您可以在 count.vocabulary_
字典中查找,其中词是键,索引(1057, 4920, …)是值。
关于您的第二个问题,predictions.shape - (1250, 2)
您得到2列是因为您调用了LogisticRegression的 predict_proba()
,它返回每个类别的概率(在您的案例中 – 2个类别)。如果您只想要预测标签,您应该调用 predict()
。