Scikit 学习垃圾邮件预测代码总是预测相同的结果
Scikit learn spam mail prediction code always predicts the same result
代码:垃圾邮件预测
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
raw_mail_data=pd.read_csv("mail_data.csv")
mail_data=raw_mail_data.where( (pd.notnull(raw_mail_data)),"" )
mail_data.loc[mail_data["Category"]=="spam","Category"]=0
mail_data.loc[mail_data["Category"]=="ham","Category"]=1
X=mail_data["Message"]
Y=mail_data["Category"]
X_train, X_test, Y_train, Y_test = train_test_split(X,
Y,
test_size=0.2,
random_state=42)
feature_extraction= TfidfVectorizer(min_df=1,stop_words="english",lowercase="True")
X_train_features=feature_extraction.fit_transform(X_train)
X_test_features=feature_extraction.transform(X_test)
Y_train=Y_train.astype('int')
Y_test=Y_test.astype('int')
model = LogisticRegression()
model.fit(X_train_features,Y_train)
prediction_on_training_data=model.predict(X_train_features)
accuracy_on_training_data=accuracy_score(Y_train,prediction_on_training_data)
print("Accuracy on training data:",accuracy_on_training_data)
prediction_on_test_data=model.predict(X_test_features)
accuracy_on_test_data=accuracy_score(Y_test,prediction_on_test_data)
print("Accuracy on test data:",accuracy_on_test_data)
inputs=input("please type a message.")
input_mail=[str(inputs)]
input_data_features=feature_extraction.transform(input_mail)
print("input_data_features:",input_data_features)
prediction=model.predict(input_data_features)
print("prediction:",prediction)
if prediction[0]==1:
print("Normal mail",prediction[0])
elif prediction[0]==0:
print("spam mail",prediction[0])
else:
print("unknown condition")
即使我输入垃圾邮件内容作为输入(折扣等),我也无法得到 0 的结果。(即垃圾邮件)代码无法正确猜测。它总是给出 1 个结果。这是什么原因?训练集和测试集的准确度分数看起来正常 (%96)。代码的编写错误是否会导致一遍遍出现相同的结果?或者我应该尝试另一种算法,如决策树?
您不应使用准确性进行模型评估,而应使用能够很好地应对 class 不平衡的度量。
看看https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html
如果您平均每个 class 的精度,那么 class 具有少量样本的 es 也会得到优化。
仅使用准确性,您的 classifier 可以学到的最好的东西就是总是说:没有垃圾邮件。 (因为毕竟大多数邮件都不是垃圾邮件。)
我对你的问题有不同的看法。垃圾邮件 class 在整个数据集中大约占 13%,这对于训练目的来说绰绰有余,并且在垃圾邮件检测问题中很可能很常见。
您遇到的第一个也是主要问题是缺乏数据预处理。我检查了你的数据集,发现有很多拼写错误,这增加了字符数,甚至明显将整封电子邮件呈现为垃圾邮件的单词也经常拼写不同(FreeMsg、WINNER!!),这意味着它们将被编码由于算法不同。您需要应用词形还原器并删除标点符号。
其次,我会使用 cross-validation 检查具有分层 k-fold 的模型的结果,它处理 class 不平衡而不是随机 train/test分裂。另一种选择是 under/oversample 您的数据集,但这会产生相同的结果,但需要更多的工作。
请在查找其他 classifier 之前尝试这两个建议。逻辑回归应该能够相当容易地解决这个问题
代码:垃圾邮件预测
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
raw_mail_data=pd.read_csv("mail_data.csv")
mail_data=raw_mail_data.where( (pd.notnull(raw_mail_data)),"" )
mail_data.loc[mail_data["Category"]=="spam","Category"]=0
mail_data.loc[mail_data["Category"]=="ham","Category"]=1
X=mail_data["Message"]
Y=mail_data["Category"]
X_train, X_test, Y_train, Y_test = train_test_split(X,
Y,
test_size=0.2,
random_state=42)
feature_extraction= TfidfVectorizer(min_df=1,stop_words="english",lowercase="True")
X_train_features=feature_extraction.fit_transform(X_train)
X_test_features=feature_extraction.transform(X_test)
Y_train=Y_train.astype('int')
Y_test=Y_test.astype('int')
model = LogisticRegression()
model.fit(X_train_features,Y_train)
prediction_on_training_data=model.predict(X_train_features)
accuracy_on_training_data=accuracy_score(Y_train,prediction_on_training_data)
print("Accuracy on training data:",accuracy_on_training_data)
prediction_on_test_data=model.predict(X_test_features)
accuracy_on_test_data=accuracy_score(Y_test,prediction_on_test_data)
print("Accuracy on test data:",accuracy_on_test_data)
inputs=input("please type a message.")
input_mail=[str(inputs)]
input_data_features=feature_extraction.transform(input_mail)
print("input_data_features:",input_data_features)
prediction=model.predict(input_data_features)
print("prediction:",prediction)
if prediction[0]==1:
print("Normal mail",prediction[0])
elif prediction[0]==0:
print("spam mail",prediction[0])
else:
print("unknown condition")
即使我输入垃圾邮件内容作为输入(折扣等),我也无法得到 0 的结果。(即垃圾邮件)代码无法正确猜测。它总是给出 1 个结果。这是什么原因?训练集和测试集的准确度分数看起来正常 (%96)。代码的编写错误是否会导致一遍遍出现相同的结果?或者我应该尝试另一种算法,如决策树?
您不应使用准确性进行模型评估,而应使用能够很好地应对 class 不平衡的度量。
看看https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html
如果您平均每个 class 的精度,那么 class 具有少量样本的 es 也会得到优化。
仅使用准确性,您的 classifier 可以学到的最好的东西就是总是说:没有垃圾邮件。 (因为毕竟大多数邮件都不是垃圾邮件。)
我对你的问题有不同的看法。垃圾邮件 class 在整个数据集中大约占 13%,这对于训练目的来说绰绰有余,并且在垃圾邮件检测问题中很可能很常见。
您遇到的第一个也是主要问题是缺乏数据预处理。我检查了你的数据集,发现有很多拼写错误,这增加了字符数,甚至明显将整封电子邮件呈现为垃圾邮件的单词也经常拼写不同(FreeMsg、WINNER!!),这意味着它们将被编码由于算法不同。您需要应用词形还原器并删除标点符号。
其次,我会使用 cross-validation 检查具有分层 k-fold 的模型的结果,它处理 class 不平衡而不是随机 train/test分裂。另一种选择是 under/oversample 您的数据集,但这会产生相同的结果,但需要更多的工作。
请在查找其他 classifier 之前尝试这两个建议。逻辑回归应该能够相当容易地解决这个问题