この記事は、の一部として公開されました データサイエンスブログソン.
概要
これがあなたのための簡単なパズルです。 私はあなたにXNUMXつのタイトルを与えます、そしてあなたはどちらが偽物であるかを私に言わなければなりません。 準備? 始めましょう:
「アダニグループは、EVセクターへの投資を検討することを計画しています。」
「WiproはEVベースのスタートアップを購入することを計画しています。」
まあ、それらの見出しの両方が偽のニュースであったことがわかります。 この記事では、ディープラーニングを使用してフェイクニュースの分類を学習します。
厳しい現実は、インターネット上に多くの誤った情報と偽情報があるということです。 カナダの国際ガバナンスイノベーションセンターのためにIpsosPublic Affairsが行った2019年の調査によると、カナダ人のXNUMX%が虚偽のニュースに陥っています。
それは私に考えさせられました:記事のタイトルが偽のニュースであるかどうかを知ることができるアルゴリズムを構築することは可能ですか? まあ、それは事実のようです!
この投稿では、BERTとLSTMを使用した分類モデルの調査を行い、偽の新しい分類を特定します。
フェイクニュース分類のデータセット
Kaggleのデータセットを使用します。 著者、タイトル、その他の情報を含む2095年の記事の詳細で構成されています。 を通過します データセットを取得します。
EDA
データの分析を開始して、データからより良い洞察を得ましょう。 データセットはきれいに見えます。次に、値を0や1などのクラスRealおよびFakeにマップします。
data = pd.read_csv( '/ content / news_articles.csv')data = data [['title'、 'label']] data ['label'] = data ['label']。map({'Real': 0、 '偽物':1})data.head()
本物のニュースのサンプルが1294個、偽のニュースのサンプルが801個あるため、ニュースの比率は約62:38になります。 これは、データセットが比較的偏っていることを意味します。 私たちのプロジェクトでは、タイトルとクラスの列を検討します。
これで、データセットに存在する傾向を分析できます。 データセットのサイズを把握するために、タイトルの平均、最小、および最大の文字長を取得します。 ヒストグラムを使用してデータを視覚化します。
#タイトルの文字長-最小、平均、最大print( '平均長'、data ['title']。apply(len).mean())print( '最小長'、data ['title']。apply( len).min())print( 'Max Length'、data ['title']。apply(len).max())x = data ['title']。apply(len).plot.hist()
各タイトルの文字の範囲は2〜443であることがわかります。 また、0〜100の長さのサンプルの割合が多いこともわかります。 データセットの平均の長さは約61です。
データの前処理
次に、NLTKライブラリを使用して、データセットを前処理します。これには、次のものが含まれます。
トークン化:
これは、テキストを小さな単位に分割するプロセスです(各単語は配列内のインデックスになります)
Lemmatization:
単語の末尾をルート単語に削除します。 それは子供という言葉を子供に減らします。
ストップワード削除:
and forのような単語は、スペースを取りすぎるため、データセットから削除されます。
#nltk前処理ライブラリをインポートしてテキストを読み取り可能な形式に変換しますimport nltk from nltk.tokenize import send_tokenize from nltk.stem import WordNetLemmatizer from nltk.corpus import stopwords nltk.download( 'punkt')nltk.download( 'wordnet')nltk。 download( 'stopwords')#文字列をトークン化(リストを作成->各インデックスは単語)data ['title'] = data.apply(lambda row:nltk.word_tokenize(row ['title'])、axis = 1)#テキストのレンマ化モデルを定義します(例:ウォークはウォークに変更されます)lemmatizer = WordNetLemmatizer()#タイトルデータフレームをループし、各単語をレマタイズしますdef lemma(data):return [lemmatizer.lemmatize(w)for w in data] #データフレームに適用data ['title'] = data ['title']。apply(lemma)#すべてのストップワードを英語で定義します(it、was、forなど)stop = stopwords.words( 'english') #データフレームからそれらを削除しますdata ['title'] = data ['title']。apply(lambda x:[i for i in x if i not in stop])data.head()
このデータをテキスト分類に使用して、XNUMXつのモデルを作成します。
- An LSTMモデル (Tensorflowのwiki-words-250埋め込み)
- A ベルト モデル。
フェイクニュース分類のためのLSTMモデル
データをトレインとテストの70:30の比率に分割します。
#データをトレーニングおよびテストデータセットに分割しますtitle_train、title_test、y_train、y_test = train_test_split(titles、labels、test_size = 0.3、random_state = 1000)
モデルからテキストに基づいて予測を取得するには、それをベクトル形式でエンコードしてから、マシンで処理する必要があります。
Word2Vec Skip-Gramアーキテクチャは、TensorFlowのwiki-words-250で使用されていました。 入力に基づいて、Skip-gramはコンテキストを予測することによってトレーニングしました。
この文を例として考えてみましょう。
車で航海します。
航海という言葉は入力として渡され、XNUMXつはウィンドウサイズとして渡されました。 ウィンドウサイズとは、予測するターゲット単語の前後を意味します。 私たちの場合、単語は消えて車になります(ストップワードを除き、goは語彙化されたgoingの形式です)。
単語をワンホットエンコードすると、サイズ1 x Vの入力ベクトルが生成されます。ここで、Vは語彙のサイズです。 V行(語彙の各単語に1つ)とE列の重み行列(Eは各埋め込みのサイズを示すハイパーパラメーター)に、表現が乗算されます。 XNUMXつを除いて、入力ベクトルのすべての値はゼロです。これは、ワンホットエンコードされているためです(入力している単語を表します)。 最後に、重み行列に出力が乗算されると、XNUMXxEベクトルはその単語の埋め込みを示します。
softmax回帰分類器で構成される出力層は、1xEベクトルを受け取ります。 これは、各単語に対して0〜1の値を生成するVニューロン(語彙のワンホットエンコーディングに対応)で構築されており、その単語がウィンドウサイズにある可能性を示しています。
サイズEが250の単語埋め込みは、Tensorflowのwiki-words-250にあります。 すべての単語をループし、各単語の埋め込みを計算することにより、モデルに適用される埋め込み。 可変長のサンプルを調整するには、パッドシーケンス関数を利用する必要があります。
embed = hub.load( "https://tfhub.dev/google/Wiki-words-250/2")#各一連の単語をword2vecに変換します。 (embed(i))indiv.append(temp)#さまざまな長さの単語を考慮indiv = tf.keras.preprocessing.sequence.pad_sequences(indiv、dtype = 'float')indiv.shape
したがって、トレーニングデータには1466のサンプルがあり、最大の長さは46ワードであり、各ワードには250の特徴があります。
次に、モデルを作成します。 構成は次のとおりです。
- 1ユニットの50つのLSTMレイヤー
- 活性化関数ReLUを備えた2つの高密度層(最初の20ニューロン、5番目のXNUMXニューロン)。
- 1活性化関数シグモイドを備えた高密度出力層。
Adamオプティマイザー、バイナリクロスエントロピー損失、および精度のパフォーマンスメトリックを使用します。 モデルは10エポックにわたってトレーニングされます。 これらのハイパーパラメータをさらに自由に調整してください。
#Sequentialモデルには、高密度レイヤーの前に50セルのLSTMレイヤーがありますmodel = tf.keras.models.Sequential()model.add(tf.keras.layers.LSTM(50))model.add(tf.keras.layers.Dense( 20、activation = 'relu'))model.add(tf.keras.layers.Dense(5、activation = 'relu'))model.add(tf.keras.layers.Dense(1、activation = 'sigmoid') )#binary_crossentropy損失、Adamオプティマイザー、および精度メトリックを使用してモデルをコンパイルしますmodel.compile(optimizer = tf.keras.optimizers.Adam(learning_rate = 1e-4)、loss = "binary_crossentropy"、metrics = ['accuracy'])# 10エポックでモデルをトレーニングするmodel.fit(indiv、y_train、validation_data = [test、y_test]、epochs = 20)
テストデータで59.4%の精度が得られます。
フェイクニュース分類のためのBERTの使用
最も多くの定義を持つ英語の用語に名前を付けるように頼んだら、あなたは何と答えますか?
オックスフォード英語辞典の第XNUMX版によると、その単語は「設定」されています。
あなたがそれについて考えるならば、私たちはさまざまな設定でその用語を使用して多くの異なるステートメントを作ることができます。 次のシナリオを検討してください。
私の本は一連の文房具コレクションの一部です
チームメイトがバドミントンをしてくれました
昼食のテーブルをセットしました
Word2Vecの問題は、単語がどのように使用されていても、同じ埋め込みが生成されることです。 これに対抗するために、コンテキスト化された埋め込みを構築できるBERTを使用します。
BERTは、「トランスフォーマーからの双方向エンコーダー表現」として知られています。 トランスフォーマーモデルを使用して、注意メカニズムを利用してコンテキスト化された埋め込みを生成します。
エンコーダー-デコーダー設計は、トランスモデルで使用されていました。 エンコーダーレイヤーは、入力から学習したデータに基づいて連続表現を作成します。 前の入力は、出力を生成するデコーダーレイヤーによってモデルに配信されます。 BERTの目的はテキストからベクトル表現を構築することであるため、エンコーダーのみを使用します。
事前トレーニングと微調整
BERTは15つの方法でトレーニングを行いました。 最初の方法は、ベールに包まれた言語モデリングであることが知られています。 シーケンスを送信する前は、[MASK]トークンを使用して単語のXNUMX%を置き換えていました。 マスクされていない単語によって提供されるコンテキストを使用して、モデルはマスクされた単語を予測します。
それはによって達成されます
- 埋め込み行列を使用して、エンコーダ出力に分類レイヤーを適用します。 結果として、それは語彙と同じサイズになります。
- ソフトマックス関数を使用して単語の尤度を計算します。
XNUMX番目の戦略は、次の文を推測することです。 モデルには入力としてXNUMXつの文が与えられ、XNUMX番目の文が最初の文の後に来るかどうかを予測します。 トレーニング中、入力の半分はペアであり、残りの半分はコーパスからのランダムな文で構成されます。 XNUMXつのステートメントを区別するには、
- ここでは、最初の文の先頭に[CLS]トークンを追加し、それぞれの最後に[SEP]トークンを追加します。
- 各トークン(単語)には、テキストの場所から情報を抽出できるようにする位置の埋め込みが含まれています。 トランスフォーマーモデルには繰り返しがないため、単語の場所を本質的に理解することはできません。
- 各トークンには、文の埋め込みが与えられます(文をさらに区別します)。
Next Sentence Predictionの場合、「文分類の集約シーケンス表現」を表す[CLS]埋め込みの出力は、softmaxを使用して分類レイヤーを通過し、XNUMXつの文が連続する確率を返します。
著者による画像
BERTの実装
TensorflowハブのBERTプリプロセッサとエンコーダが使用されていました。 前述のフレームワーク(大文字と小文字の区別を削除したり、レンマ化を適用したりするなど)を介してコンテンツを実行しないでください。BERTプリプロセッサがこれを抽象化するために使用していました。
トレーニングとテストのデータを80:20の比率で分割します。
from sklearn.model_selection import train_test_split#データをトレーニングおよびテストデータセットに分割title_train、title_test、y_train、y_test = train_test_split(titles、labels、test_size = 0.2、random_state = 1000)
次に、Bertプリプロセッサとエンコーダをロードします
#tensorflow_hubからbertプリプロセッサーとbertエンコーダーを使用-3_H-12_A-768 / 12 ')
これで、ニューラルネットワークで作業できるようになりました。 これは機能モデルである必要があり、各レイヤーの出力が次のレイヤーへの引数として機能します。
- 1入力レイヤー:モデルに文を渡すために使用されます。
- bert_preprocessレイヤー:入力テキストを前処理します。
- bert_encoderレイヤー:前処理されたトークンをBERTエンコーダーに渡します。
- 1のドロップアウトレイヤー0.2つ。 BERTエンコーダーpooled_outputが渡されます。
- 2個と10個のニューロンを持つ1つの密な層。 XNUMXつ目はReLU活性化関数を使用し、XNUMXつ目はシグモイドです。
import tensorflow as tf#入力レイヤーinput_layer = tf.keras.layers.Input(shape =()、dtype = tf.string、name = 'news')#処理されたBERTレイヤー= bert_preprocess(input_layer)output = bert_encoder(processed)#完全に接続されたレイヤーlayer = tf.keras.layers.Dropout(0.2、name = 'dropout')(output ['pooled_output'])layer = tf.keras.layers.Dense(10、activation = 'relu'、name = ' hidden ')(layer)layer = tf.keras.layers.Dense(1、activation =' sigmoid '、name =' output ')(layer)model = tf.keras.Model(inputs = [input_layer]、outputs = [層])
ご覧のとおり、「プールされた出力」はドロップアウトレイヤーに送信されます。 この値は、テキストの全体的なシーケンス表現を表します。 前述のように、これは[CLS]トークン出力の表現です。
Adamオプティマイザー、バイナリクロスエントロピー損失、および精度パフォーマンスメトリックが使用されていました。 XNUMXつのエポックの間、モデルはトレーニングされていました。 これらのハイパーパラメータをさらに微調整してください。
#adamオプティマイザー、binary_crossentropy損失、および精度メトリックでモデルをコンパイルしますmodel.compile(optimizer = 'adam'、loss = 'binary_crossentropy'、metrics = ['accuracy'])#5エポックでモデルをトレーニングしますmodel.fit(title_train、y_train 、epochs = 5)#テストデータモデルでモデルを評価します。evaluate(title_test、y_test)
著者による画像
上記のように、モデルが61.33%の精度を達成したことがわかります。
まとめ
モデルのパフォーマンスを向上させるには:
- 大規模なデータセットでモデルをトレーニングします。
- モデルのハイパーパラメータを微調整します。
この投稿が、偽のニュース分類のためのNLP手法について洞察に満ち、理解が深まっていることをご理解いただけたでしょうか。
私たちのブログでもっと記事を読んでください。 クリック こちら.
参考文献
画像– 1: による写真 ローマンクラフト on Unsplash
この記事に示されているメディアは Analytics Vidhya が所有するものではなく、著者の裁量で使用されています。