- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在对 twitter 数据进行情感分析时,我遇到了一个我无法解决的问题。我想训练一个随机森林分类器来检测仇恨言论。因此,我使用了一个带有标记的数据集,其中的推文被标记为 1 表示仇恨言论,0 表示正常推文。对于矢量化,我使用 Word2Vec。我首先进行了一个超参数化来为分类器找到好的参数。
在超参数化期间,我使用了重复的分层 KFold 交叉验证(评分 = 准确性)
这里的平均准确率约为 99.6%。然而,一旦我将模型应用于测试数据集并绘制混淆矩阵,准确率仅高于 50%,这对于二元分类器来说当然是糟糕的。
我成功地对 Bag of Words 使用了完全相同的方法,并且在这里完全没有问题。
有人可以快速查看我的代码吗?那会很有帮助。我就是找不到哪里出了问题。非常感谢!
(我还将代码上传到 google collab,以防您更容易:https://colab.research.google.com/drive/15BzElijL3vwa_6DnLicxRvcs4SPDZbpe?usp=sharing)
首先我预处理我的数据:
train_csv = pd.read_csv(r'/content/drive/My Drive/Colab Notebooks/MLDA_project/data2/train.csv')
train = train_csv
#check for missing values (result shows that there are no missing values)
train.isna().sum()
# remove the tweet IDs
train.drop(train.columns[0], axis = "columns", inplace = True)
# create a new column to save the cleansed tweets
train['training_tweet'] = np.nan
# remove special/unknown characters
train.replace('[^a-zA-Z#]', ' ', inplace = True, regex = True)
# generate stopword list and add the twitter handles "user" to the stopword list
stopwords = sw.words('english')
stopwords.append('user')
# convert to lowercase
train = train.applymap(lambda i:i.lower() if type(i) == str else i)
# execute tokenization and lemmatization
lemmatizer = WordNetLemmatizer()
for i in range(len(train.index)):
#tokenize the tweets from the column "tweet"
words = nltk.word_tokenize(train.iloc[i, 1])
#consider words with more than 3 characters
words = [word for word in words if len(word) > 3]
#exclude words in stopword list
words = [lemmatizer.lemmatize(word) for word in words if word not in set(stopwords)]
#Join words again
train.iloc[i, 2] = ' '.join(words)
words = nltk.word_tokenize(train.iloc[i, 2])
train.drop(train.columns[1], axis = "columns", inplace = True)
majority = train[train.label == 0]
minority = train[train.label == 1]
# upsample minority class
minority_upsampled = resample(minority, replace = True, n_samples = len(majority))
# combine majority class with upsampled minority class
train_upsampled = pd.concat([majority, minority_upsampled])
train = train_upsampled
np.random.seed(10)
train = train.sample(frac = 1)
train = train.reset_index(drop = True)
现在
train
有第 0 列的标签和第 1 列的预处理推文。
def W2Vvectorize(X_train):
tokenize=X_train.apply(lambda x: x.split())
w2vec_model=gensim.models.Word2Vec(tokenize,min_count = 1, size = 100, window = 5, sg = 1)
w2vec_model.train(tokenize,total_examples= len(X_train), epochs=20)
w2v_words = list(w2vec_model.wv.vocab)
vector=[]
from tqdm import tqdm
for sent in tqdm(tokenize):
sent_vec=np.zeros(100)
count =0
for word in sent:
if word in w2v_words:
vec = w2vec_model.wv[word]
sent_vec += vec
count += 1
if count != 0:
sent_vec /= count #normalize
vector.append(sent_vec)
return vector
我将数据集拆分为测试集和训练集,并使用上述定义的 W2V 对两个子集进行矢量化:
x = train["training_tweet"]
y = train["label"]
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, stratify=train['label'])
print('X Train Shape = total * 0,8 =', X_train.shape)
print('y Train Shape = total * 0,8 =', y_train.shape)
print('X Test Shape = total * 0,2 =', X_test.shape)
print('y Test Shape = total * 0,2 =', y_test.shape) # change 0,4 & 0,6
train_tf_w2v = W2Vvectorize(X_train)
test_tf_w2v = W2Vvectorize(X_test)
现在我进行超参数化:
# define models and parameters
model = RandomForestClassifier()
n_estimators = [10, 100, 1000]
max_features = ['sqrt', 'log2']
# define grid search
grid = dict(n_estimators=n_estimators,max_features=max_features)
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0)
grid_result = grid_search.fit(train_tf_w2v, y_train)
# summarize results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
print("%f (%f) with: %r" % (mean, stdev, param))
这导致以下输出:
Best: 0.996628 using {'max_features': 'log2', 'n_estimators': 1000}
0.995261 (0.000990) with: {'max_features': 'sqrt', 'n_estimators': 10}
0.996110 (0.000754) with: {'max_features': 'sqrt', 'n_estimators': 100}
0.996081 (0.000853) with: {'max_features': 'sqrt', 'n_estimators': 1000}
0.995885 (0.000872) with: {'max_features': 'log2', 'n_estimators': 10}
0.996481 (0.000691) with: {'max_features': 'log2', 'n_estimators': 100}
0.996628 (0.000782) with: {'max_features': 'log2', 'n_estimators': 1000}
接下来,我想使用模型绘制带有测试数据的混淆矩阵:
clf = RandomForestClassifier(max_features = 'log2', n_estimators=1000)
clf.fit(train_tf_w2v, y_train)
name = clf.__class__.__name__
expectation = y_test
test_prediction = clf.predict(test_tf_w2v)
acc = accuracy_score(expectation, test_prediction)
pre = precision_score(expectation, test_prediction)
rec = recall_score(expectation, test_prediction)
f1 = f1_score(expectation, test_prediction)
fig, ax = plt.subplots(1,2, figsize=(14,4))
plt.suptitle(f'{name} \n', fontsize = 18)
plt.subplots_adjust(top = 0.8)
skplt.metrics.plot_confusion_matrix(expectation, test_prediction, ax=ax[0])
skplt.metrics.plot_confusion_matrix(expectation, test_prediction, normalize=True, ax = ax[1])
plt.show()
print(f"for the {name} we receive the following values:")
print("Accuracy: {:.3%}".format(acc))
print('Precision score: {:.3%}'.format(pre))
print('Recall score: {:.3%}'.format(rec))
print('F1 score: {:.3%}'.format(f1))
这输出:
最佳答案
呃...现在我觉得自己很愚蠢。我发现出了什么问题。
在训练/测试分割之后,我将两个子集独立发送到 W2Vvectorize()
功能。
train_tf_w2v = W2Vvectorize(X_train)
test_tf_w2v = W2Vvectorize(X_test)
从那里
W2Vvectorize()
函数基于两个独立的子集训练两个独立的 Word2Vec 模型。因此,当我通过矢量化测试数据时
test_tf_w2v
对于我训练有素的 RandomForest 分类器,为了检查测试集的准确性是否也正确,在训练有素的 RandomForest 分类器看来,就好像测试集将使用不同的语言一样。两个独立的 word2vec 模型只是以不同的方式进行矢量化。
def W2Vvectorize(X_train):
tokenize=X_train.apply(lambda x: x.split())
vector=[]
for sent in tqdm(tokenize):
sent_vec=np.zeros(100)
count =0
for word in sent:
if word in w2v_words:
vec = w2vec_model.wv[word]
sent_vec += vec
count += 1
if count != 0:
sent_vec /= count #normalize
vector.append(sent_vec)
return vector
Word2Vec 训练与此分开:
x = train["training_tweet"]
y = train["label"]
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, stratify=train['label'])
print('X Train Shape = total * 0,8 =', X_train.shape)
print('y Train Shape = total * 0,8 =', y_train.shape)
print('X Test Shape = total * 0,2 =', X_test.shape)
print('y Test Shape = total * 0,2 =', y_test.shape) #
tokenize=X_train.apply(lambda x: x.split())
w2vec_model=gensim.models.Word2Vec(tokenize,min_count = 1, size = 100, window = 5, sg = 1)
w2vec_model.train(tokenize,total_examples= len(X_train), epochs=20)
w2v_words = list(w2vec_model.wv.vocab)
train_tf_w2v = W2Vvectorize(X_train)
test_tf_w2v = W2Vvectorize(X_test)
所以 Word2Vec 模型训练只在训练数据上进行。然而,测试数据的矢量化必须使用完全相同的 Word2Vec 模型进行。
关于machine-learning - Word2Vec - 具有高交叉验证分数的模型对测试数据的表现非常糟糕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62880636/
直接从 Python 代码运行 pylint 时,我似乎无法获得任何返回值。从命令行运行它会生成一个漂亮的报告,在底部有一个总结分数。 我已经尝试将“Run”的返回值放入一个变量中,并获取它的“rep
我是 Python 新手,正在尝试学习单词检测。我有一个带有单词的数据框 sharina['transcript'] Out[25]: 0 thank you for calling my
http://jsfiddle.net/q8P7Y/ 我在最后显示最终分数时遇到问题,有很多方法可以做到这一点,但我不确定什么是最好的。 正如你所看到的,下一个按钮只是 div 的显示/隐藏,而不是页
我使用滑动 slider 并有计数器分数。它计数很好,但我需要计数 =(所有幻灯片 - 1)。例如,如果我有 20 张幻灯片,我想显示总数 19。有什么办法可以做到这一点吗?我使用他们网站上的常规 j
我使用滑动 slider 并有计数器分数。它计数很好,但我需要计数 =(所有幻灯片 - 1)。例如,如果我有 20 张幻灯片,我想显示总数 19。有什么办法可以做到这一点吗?我使用他们网站上的常规 j
我试图在按下按钮时添加分数,分数显示在 JTextField 中,但是当按下按钮时,分数会添加,它显示为 0。我有一个存储分数的整数字段 private int score=0; yesButton
我可以在选项(单选按钮)随机播放之前计算分数/分数,如下面的代码所示。在Collection.shuffle()之前,选项是固定的,因为 CorrectChoice将始终分配给c2单选按钮。那么我可以
我在这里的代码只能得到87%的代码,因为“带有非正参数的加法参数什么也没做。我该如何解决呢?我尝试了更多的方法,但是我什至无法解决此错误在同学的帮助下 说明是: 对于此分配,您将创建一个存储分数的类。
昨天,我尝试以一种方式执行此操作...今天我尝试另一种方式,但仍然卡住了。我必须找到一种使用整数除法和取模来做到这一点的方法。这是我的代码,后面是错误消息。 public int evaluateFr
我这里有一些特殊字符: http://209.141.56.244/test/char.php 但是当我在这里通过 ajax 抓取这个文件时,它们显示为 back ?标记: http://209.14
我得到了一张图表 G与 n顶点,标记自 1至 n (2 a_1 -> a_2 -> ... a_k -> n A然后将占据 1 的所有“子节点”节点, a_1 , ... a_x (其中 x = ce
我有一个看起来像这样的 mongodb 集合: db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'}
我试图更好地了解 lucene 如何对我的搜索进行评分,以便我可以对我的搜索配置或文档内容进行必要的调整。 以下是分数明细的一部分。 产品: 0.34472802 = queryWeight,
在我网站上用户生成的帖子下,我有一个类似亚马逊的评级系统: Was this review helpful to you: Yes | No 如果有投票,我会在该行上方显示结果,如下所示:
对于我的项目,我需要找出哪些搜索结果被视为“良好”匹配。目前,分数因查询而异,因此需要以某种方式对它们进行标准化。标准化分数将允许选择高于给定阈值的结果。 我为 Lucene 找到了几个解决方案: h
我有一个由 57 个变量组成的数据文件。由于测量水平不均匀,我想将其中的大约 12 个转换为 z 分数。我查找了互联网资源和帮助文件。一个互联网资源建议我需要 Rbasic 包(不存在)。我使用了 s
我对 SOLR 核心运行查询并使用过滤器限制结果例如 fq: {!frange l=0.7 }query($q)。我知道 SOLR 分数不有绝对意义,但是0.7(只是一个例子)是计算出来的基于用户输入
我想找到不同的方法来解决我遇到的现实生活问题:想象一下进行一场比赛或一场游戏,在此期间用户收集积分。您必须构建一个查询来显示具有最佳“n”分数的用户列表。 我举一个例子来澄清。假设这是用户表,其中包含
我有很多 wiki 页面,我想训练一个分类器,看看是否可以通过一些特征(包括段落的位置和段落的 lucene 分数)来确定重点搜索的位置。我尝试将每个段落视为一个文档,这使我能够获得每个段落的 luc
我是 R 编程新手,在使用一些基本代码时遇到问题。 我有一个包含以下列的数据框:条件(因子)、用户(因子)和灵敏度(int)。对于每个用户有 20 个敏感项。我需要为每个用户创建一个具有标准化敏感度分
我是一名优秀的程序员,十分优秀!