序文
WeChatの急速な発展に伴い、仕事や生活におけるコミュニケーションもそれに依存していますが、電子メールの形式的で規範的な性質のため、それでもかけがえのないものです。ただし、社内の仕事用メールボックスでも個人用メールボックスでも、ビジネス広告、割引やプロモーション、マカオのゲームメール、財務プロモーション情報など、あらゆる種類のスパムを常に受信します。スパムをどのように分類しても、常に存在します。ネットをすり抜ける魚。最も重要なことは、ユーザーごとにスパムの定義が異なることです。
さらに、ほとんどのユーザーはネットワークセキュリティについて比較的一般的な認識を持っています。誤ってスパムメールをクリックしたり、スパムメールが職場のキー文字をかき消したりすると、個人や企業に損失をもたらします。
スパムの特定は常に問題点であり困難でした。この方法はベイズ学習、確率統計、または深層学習に基づく方法にすぎませんが、ビジネスシナリオの多様化により、スパムのパターンが多すぎるため、従来のスパム傍受デバイスは常に少し遅れています。
したがって、同じデータセットに対してさまざまな方法を徐々に試し、スパムを識別して分類する予定です。このカスタマイズされたスパム識別ツールによって、ユーザーのメールボックスエクスペリエンスが大幅に向上することを願っています。
1.全体的なアイデア
一般に、メールは送信者、受信者、CC、件名、時間、コンテンツなどの要素に分けることができるため、スパムは主に上記の要素の送信者、件名、コンテンツを介して発生すると考えるのが自然です。メールの判断。
したがって、上記の要素を順番に分析します。
- スパムコンテンツの分類(スパムコンテンツを抽出して判断する)
- 中国のスパム分類
- 英語のスパム分類
- スパムヘッダーの分類
- スパマー分類
最後に、スパムの正確な分類を実現するために、これらの3つの側面に従って包括的な判断を下すことができます。この記事では、電子メールの内容に従ってスパムを分類します。
2.中国の電子メールコンテンツ分類の実装手順
1.データセットの紹介
TREC 2006 Spam Track Public Corporaまず、パブリックスパムコーパスであるTREC 2006 Spam TrackPublicCorporaを選択します。コーパスは、テキスト検索に関する国際会議によって提供され、英語のデータセット(trec06p)と中国語のデータセット(trec06c)に分割されます。コーパスに含まれる電子メールはすべて実際の電子メールから派生し、電子メールの元の形式と内容を保持します。
ファイルディレクトリの形式:delayとfullは、それぞれスパムフィルターのフィルタリングメカニズムです。fullディレクトリでは、これは理想的な電子メール分類結果であり、調査のラベルと見なすことができます。
trec06c│└───データ
││000││001││ ...
│└───215└───遅延
││index└───full││index
_ _ _ _
2.データの読み込み
2.1 eml形式からメール要素を抽出し、それらをcsvとして保存します
現在のデータセットは電子メールの形式で保存され、インデックスによってスパムとしてマークされるため、最初に送信者、受信者、cc、件名、送信時間、コンテンツ、および各電子メールのスパムかどうかを抽出します。ラベル。
mailTable=pd.DataFrame(columns=('Sender','Receiver','CarbonCopy','Subject','Date','Body','isSpam'))
# path='trec06p/full/../data/000/004'
# emlContent= emlAnayalyse(path)
# print(emlContent)
f = open('trec06c/full/index', 'r')
csvfile=open('mailChinese.csv','w',newline='',encoding='utf-8')
writer=csv.writer(csvfile)
for line in f:
str_list = line.split(" ")
print(str_list[1])
# 设置垃圾邮件的标签为0
if str_list[0] == 'spam':
label = '0'
# 设置正常邮件标签为1
elif str_list[0] == 'ham':
label = '1'
emlContent= emlAnayalyse('trec06c/full/' + str(str_list[1].split("\n")[0]))
if emlContent is not None:
writer.writerow([emlContent[0],emlContent[1],emlContent[2],emlContent[3],emlContent[4],emlContent[5],label])
emlAnayalyze関数は、フランカーライブラリのmimeを使用して、メールの送信者、受信者、cc、件名、送信時間、コンテンツ、その他の要素を抽出します。詳細については、私の記事を参照してください。Pythonの数行のコードメール解析を実現する
2.2分類のためにcsvから電子メールコンテンツを抽出する
def get_data(path):
'''
获取数据
:return: 文本数据,对应的labels
'''
maildf = pd.read_csv(path,header=None, names=['Sender','Receiver','“CarbonCopy','Subject','Date','Body','isSpam'])
filteredmaildf=maildf[maildf['Body'].notnull()]
corpus=filteredmaildf['Body']
labels=filteredmaildf['isSpam']
corpus=list(corpus)
labels=list(labels)
return corpus, labels
get_data関数を使用してcsv形式でデータを読み取り、内容が空でないデータと対応するラベルを抽出します。
合計40348個のデータを見ることができます。
from sklearn.model_selection import train_test_split
# 对数据进行划分
train_corpus, test_corpus, train_labels, test_labels = train_test_split(corpus, labels,
test_size=0.3, random_state=0)
次に、トレーニングセットと検証セットがsklearn.model_selectionライブラリのtrain_test_split関数によって分割されます。
# 进行归一化
norm_train_corpus = normalize_corpus(train_corpus)
norm_test_corpus = normalize_corpus(test_corpus)
次に、データはnormalize_corpus関数によって前処理されます。
def textParse(text):
listOfTokens=jieba.lcut(text)
newList=[re.sub(r'\W*','',s) for s in listOfTokens]
filtered_text=[tok for tok in newList if len(tok)>0]
return filtered_text
def remove_stopwords(tokens):
filtered_tokens = [token for token in tokens if token not in stopword_list]
filtered_text = ' '.join(filtered_tokens)
return filtered_text
def normalize_corpus(corpus, tokenize=False):
normalized_corpus = []
for text in corpus:
filtered_text = textParse(filtered_text)
filtered_text = remove_stopwords(filtered_text)
normalized_corpus.append(filtered_text)
return normalized_corpus
これには、textParseとremove_stopwordsの2つのデータ前処理操作が含まれます。
textParse関数は、最初にjiebaを介して単語のセグメンテーションを実行し、次に不要な文字を削除します。
remove_stopwords関数は、最初にstop_words.txtストップワードリストをロードし、次にストップワードを削除します。
これにより、データの前処理が可能になります。
2.3単語ベクトルの構築
# 词袋模型特征
bow_vectorizer, bow_train_features = bow_extractor(norm_train_corpus)
bow_test_features = bow_vectorizer.transform(norm_test_corpus)
# tfidf 特征
tfidf_vectorizer, tfidf_train_features = tfidf_extractor(norm_train_corpus)
tfidf_test_features = tfidf_vectorizer.transform(norm_test_corpus)
bow_extractor関数とtfidf_extractor関数は、トレーニングセットをそれぞれbag-of-wordsモデル機能とtfidf機能に変換します。
from sklearn.feature_extraction.text import CountVectorizer
def bow_extractor(corpus, ngram_range=(1, 1)):
vectorizer = CountVectorizer(min_df=1, ngram_range=ngram_range)
features = vectorizer.fit_transform(corpus)
return vectorizer, features
from sklearn.feature_extraction.text import TfidfTransformer
def tfidf_transformer(bow_matrix):
transformer = TfidfTransformer(norm='l2',
smooth_idf=True,
use_idf=True)
tfidf_matrix = transformer.fit_transform(bow_matrix)
return transformer, tfidf_matrix
from sklearn.feature_extraction.text import TfidfVectorizer
def tfidf_extractor(corpus, ngram_range=(1, 1)):
vectorizer = TfidfVectorizer(min_df=1,
norm='l2',
smooth_idf=True,
use_idf=True,
ngram_range=ngram_range)
features = vectorizer.fit_transform(corpus)
return vectorizer, features
2.4モデルのトレーニングと評価
上記の2つの異なるベクトル表現について、ベイズ分類器、ロジスティック回帰分類器、およびサポートベクターマシン分類器をそれぞれトレーニングして、効果を検証します。
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import SGDClassifier
from sklearn.linear_model import LogisticRegression
mnb = MultinomialNB()
svm = SGDClassifier(loss='hinge', n_iter_no_change=100)
lr = LogisticRegression()
# 基于词袋模型的多项朴素贝叶斯
print("基于词袋模型特征的贝叶斯分类器")
mnb_bow_predictions = train_predict_evaluate_model(classifier=mnb,
train_features=bow_train_features,
train_labels=train_labels,
test_features=bow_test_features,
test_labels=test_labels)
# 基于词袋模型特征的逻辑回归
print("基于词袋模型特征的逻辑回归")
lr_bow_predictions = train_predict_evaluate_model(classifier=lr,
train_features=bow_train_features,
train_labels=train_labels,
test_features=bow_test_features,
test_labels=test_labels)
# 基于词袋模型的支持向量机方法
print("基于词袋模型的支持向量机")
svm_bow_predictions = train_predict_evaluate_model(classifier=svm,
train_features=bow_train_features,
train_labels=train_labels,
test_features=bow_test_features,
test_labels=test_labels)
joblib.dump(svm, 'svm_bow.pkl')
# 基于tfidf的多项式朴素贝叶斯模型
print("基于tfidf的贝叶斯模型")
mnb_tfidf_predictions = train_predict_evaluate_model(classifier=mnb,
train_features=tfidf_train_features,
train_labels=train_labels,
test_features=tfidf_test_features,
test_labels=test_labels)
# 基于tfidf的逻辑回归模型
print("基于tfidf的逻辑回归模型")
lr_tfidf_predictions=train_predict_evaluate_model(classifier=lr,
train_features=tfidf_train_features,
train_labels=train_labels,
test_features=tfidf_test_features,
test_labels=test_labels)
# 基于tfidf的支持向量机模型
print("基于tfidf的支持向量机模型")
svm_tfidf_predictions = train_predict_evaluate_model(classifier=svm,
train_features=tfidf_train_features,
train_labels=train_labels,
test_features=tfidf_test_features,
test_labels=test_labels)
出力は次のとおりです
要約する
電子メールの内容についてさまざまなモデルをトレーニングし、それを2つの異なる単語ベクトルに変換することにより、tfidfベースのサポートベクターマシンモデルが最高の効果を発揮し、98%の正解率を達成できます。
この記事はシリーズ「ゼロからのメール認識」の2番目の記事です。あなたがそれをサポートしてくれることを願っています!
参照する:
PaddleNLPによるスパムの識別(1):精度98.5%のスパム分類器-PaddleAIStudio-人工知能の学習およびトレーニングコミュニティ