1598542920
Snippets for Sublime Text with the key features of Vue.js
v
vue
⇢ Vue instancevued
⇢ Vue directivevuef
⇢ Vue filtervuenexttick
⇢ Vue.nextTick()
vuec
⇢ Vue componentvueccomputed
⇢ Vue computed propsvuecdata
⇢ Vue component datavuecmethods
⇢ Vue component methodsvuecmixins
⇢ Vue component mixinsvuecprops
⇢ Vue component propsvuecwatch
⇢ Vue component watchvueht
⇢ this.$http()
vuehtget
⇢ this.$http.get()
vuehtpost
⇢ this.$http.post()
vuert
⇢ this.$route
vuertgo
⇢ this.$route.router.go()
vuex
⇢ Vuex instance
v-bind
⇢ :prop="data"
v-el
⇢ v-el:el-name
v-else
⇢ <div v-else>
v-for
⇢ <div v-for="item in items">
v-if
⇢ <div v-if="">
v-link
⇢ <a v-link="">
v-on
⇢ @evt="callback"
v-ref
⇢ v-ref:ref-name
Just Remove and Install again.
Author: filipelinhares
Source Code: https://github.com/filipelinhares/vuejs-snippets-sublime
#vuejs #vue #javascript
1650870267
In the previous chapters you've learnt how to select individual elements on a web page. But there are many occasions where you need to access a child, parent or ancestor element. See the JavaScript DOM nodes chapter to understand the logical relationships between the nodes in a DOM tree.
DOM node provides several properties and methods that allow you to navigate or traverse through the tree structure of the DOM and make changes very easily. In the following section we will learn how to navigate up, down, and sideways in the DOM tree using JavaScript.
You can use the firstChild
and lastChild
properties of the DOM node to access the first and last direct child node of a node, respectively. If the node doesn't have any child element, it returns null
.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
console.log(main.firstChild.nodeName); // Prints: #text
var hint = document.getElementById("hint");
console.log(hint.firstChild.nodeName); // Prints: SPAN
</script>
Note: The
nodeName
is a read-only property that returns the name of the current node as a string. For example, it returns the tag name for element node,#text
for text node,#comment
for comment node,#document
for document node, and so on.
If you notice the above example, the nodeName
of the first-child node of the main DIV element returns #text instead of H1. Because, whitespace such as spaces, tabs, newlines, etc. are valid characters and they form #text nodes and become a part of the DOM tree. Therefore, since the <div>
tag contains a newline before the <h1>
tag, so it will create a #text node.
To avoid the issue with firstChild
and lastChild
returning #text or #comment nodes, you could alternatively use the firstElementChild
and lastElementChild
properties to return only the first and last element node, respectively. But, it will not work in IE 9 and earlier.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
alert(main.firstElementChild.nodeName); // Outputs: H1
main.firstElementChild.style.color = "red";
var hint = document.getElementById("hint");
alert(hint.firstElementChild.nodeName); // Outputs: SPAN
hint.firstElementChild.style.color = "blue";
</script>
Similarly, you can use the childNodes
property to access all child nodes of a given element, where the first child node is assigned index 0. Here's an example:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.childNodes;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
The childNodes
returns all child nodes, including non-element nodes like text and comment nodes. To get a collection of only elements, use children
property instead.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.children;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
1594024630
Want to Hire VueJS Developer to develop an amazing app?
Hire Dedicated VueJS Developers on the contract (time/project) basis providing regular reporting about your app. We, at HourlyDeveloper.io, implement the right strategic approach to offer a wide spectrum of vue.js development services to suit your requirements at most competitive prices.
Consult with us:- https://bit.ly/2C5M6cz
#hire dedicated vuejs developers #vuejs developer #vuejs development company #vuejs development services #vuejs development #vuejs developer
1646033280
Untersuchen des Fake-News-Datensatzes, Durchführen von Datenanalysen wie Wortwolken und Ngrams und Feinabstimmen des BERT-Transformators, um einen Fake-News-Detektor in Python mithilfe der Transformer-Bibliothek zu erstellen.
Fake News sind die absichtliche Verbreitung falscher oder irreführender Behauptungen als Nachrichten, bei denen die Aussagen absichtlich irreführend sind.
Zeitungen, Boulevardzeitungen und Zeitschriften wurden durch digitale Nachrichtenplattformen, Blogs, Social-Media-Feeds und eine Vielzahl mobiler Nachrichtenanwendungen ersetzt. Nachrichtenorganisationen profitierten von der zunehmenden Nutzung sozialer Medien und mobiler Plattformen, indem sie ihren Abonnenten minutenaktuelle Informationen lieferten.
Die Verbraucher haben jetzt sofortigen Zugriff auf die neuesten Nachrichten. Diese digitalen Medienplattformen haben aufgrund ihrer einfachen Anbindung an den Rest der Welt an Bedeutung gewonnen und ermöglichen es den Benutzern, Ideen zu diskutieren und auszutauschen und Themen wie Demokratie, Bildung, Gesundheit, Forschung und Geschichte zu debattieren. Gefälschte Nachrichten auf digitalen Plattformen werden immer beliebter und werden für Profitzwecke wie politische und finanzielle Gewinne verwendet.
Da das Internet, soziale Medien und digitale Plattformen weit verbreitet sind, kann jeder ungenaue und voreingenommene Informationen verbreiten. Die Verbreitung von Fake News lässt sich kaum verhindern. Es gibt einen enormen Anstieg bei der Verbreitung falscher Nachrichten, die nicht auf einen Sektor wie Politik beschränkt sind, sondern Sport, Gesundheit, Geschichte, Unterhaltung sowie Wissenschaft und Forschung umfassen.
Es ist wichtig, falsche und richtige Nachrichten zu erkennen und zu unterscheiden. Eine Methode besteht darin, einen Experten entscheiden zu lassen und alle Informationen auf Fakten zu überprüfen, aber dies kostet Zeit und erfordert Fachwissen, das nicht geteilt werden kann. Zweitens können wir Tools für maschinelles Lernen und künstliche Intelligenz verwenden, um die Identifizierung von gefälschten Nachrichten zu automatisieren.
Online-Nachrichteninformationen umfassen verschiedene unstrukturierte Formatdaten (wie Dokumente, Videos und Audio), aber wir konzentrieren uns hier auf Nachrichten im Textformat. Mit dem Fortschritt des maschinellen Lernens und der Verarbeitung natürlicher Sprache können wir jetzt den irreführenden und falschen Charakter eines Artikels oder einer Aussage erkennen.
Mehrere Studien und Experimente werden durchgeführt, um Fake News in allen Medien aufzudecken.
Unser Hauptziel dieses Tutorials ist:
Hier das Inhaltsverzeichnis:
In dieser Arbeit haben wir den Fake-News-Datensatz von Kaggle verwendet , um nicht vertrauenswürdige Nachrichtenartikel als Fake News zu klassifizieren. Wir verfügen über einen vollständigen Trainingsdatensatz mit den folgenden Merkmalen:
id
: eindeutige ID für einen Nachrichtenartikeltitle
: Titel eines Nachrichtenartikelsauthor
: Autor des Nachrichtenartikelstext
: Text des Artikels; könnte unvollständig seinlabel
: ein Etikett, das den Artikel als potenziell unzuverlässig markiert, gekennzeichnet durch 1 (unzuverlässig oder gefälscht) oder 0 (zuverlässig).Es ist ein binäres Klassifizierungsproblem, bei dem wir vorhersagen müssen, ob eine bestimmte Nachricht zuverlässig ist oder nicht.
Wenn Sie ein Kaggle-Konto haben, können Sie den Datensatz einfach von der dortigen Website herunterladen und die ZIP-Datei entpacken.
Ich habe den Datensatz auch in Google Drive hochgeladen, und Sie können ihn hier herunterladen oder die gdown
Bibliothek verwenden, um ihn automatisch in Google Colab- oder Jupyter-Notebooks herunterzuladen:
$ pip install gdown
# download from Google Drive
$ gdown "https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t"
Downloading...
From: https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t
To: /content/fake-news.zip
100% 48.7M/48.7M [00:00<00:00, 74.6MB/s]
Entpacken der Dateien:
$ unzip fake-news.zip
Im aktuellen Arbeitsverzeichnis werden drei Dateien angezeigt: train.csv
, test.csv
, und submit.csv
, die wir train.csv
im Großteil des Tutorials verwenden werden.
Installieren der erforderlichen Abhängigkeiten:
$ pip install transformers nltk pandas numpy matplotlib seaborn wordcloud
Hinweis: Wenn Sie sich in einer lokalen Umgebung befinden, stellen Sie sicher, dass Sie PyTorch für GPU installieren, gehen Sie zu dieser Seite für eine ordnungsgemäße Installation.
Lassen Sie uns die wesentlichen Bibliotheken für die Analyse importieren:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
Die NLTK-Korpora und -Module müssen mit dem standardmäßigen NLTK-Downloader installiert werden:
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
Der Fake-News-Datensatz umfasst Original- und fiktive Artikeltitel und -texte verschiedener Autoren. Lassen Sie uns unseren Datensatz importieren:
# load the dataset
news_d = pd.read_csv("train.csv")
print("Shape of News data:", news_d.shape)
print("News data columns", news_d.columns)
Ausgabe:
Shape of News data: (20800, 5)
News data columns Index(['id', 'title', 'author', 'text', 'label'], dtype='object')
So sieht der Datensatz aus:
# by using df.head(), we can immediately familiarize ourselves with the dataset.
news_d.head()
Ausgabe:
id title author text label
0 0 House Dem Aide: We Didn’t Even See Comey’s Let... Darrell Lucus House Dem Aide: We Didn’t Even See Comey’s Let... 1
1 1 FLYNN: Hillary Clinton, Big Woman on Campus - ... Daniel J. Flynn Ever get the feeling your life circles the rou... 0
2 2 Why the Truth Might Get You Fired Consortiumnews.com Why the Truth Might Get You Fired October 29, ... 1
3 3 15 Civilians Killed In Single US Airstrike Hav... Jessica Purkiss Videos 15 Civilians Killed In Single US Airstr... 1
4 4 Iranian woman jailed for fictional unpublished... Howard Portnoy Print \nAn Iranian woman has been sentenced to... 1
Wir haben 20.800 Zeilen, die fünf Spalten haben. Sehen wir uns einige Statistiken der text
Spalte an:
#Text Word startistics: min.mean, max and interquartile range
txt_length = news_d.text.str.split().str.len()
txt_length.describe()
Ausgabe:
count 20761.000000
mean 760.308126
std 869.525988
min 0.000000
25% 269.000000
50% 556.000000
75% 1052.000000
max 24234.000000
Name: text, dtype: float64
Statistiken für die title
Spalte:
#Title statistics
title_length = news_d.title.str.split().str.len()
title_length.describe()
Ausgabe:
count 20242.000000
mean 12.420709
std 4.098735
min 1.000000
25% 10.000000
50% 13.000000
75% 15.000000
max 72.000000
Name: title, dtype: float64
Die Statistiken für die Trainings- und Testsätze lauten wie folgt:
text
Attribut hat eine höhere Wortzahl mit durchschnittlich 760 Wörtern und 75 % mit mehr als 1000 Wörtern.title
Attribut ist eine kurze Aussage mit durchschnittlich 12 Wörtern, und 75 % davon sind ungefähr 15 Wörter.Unser Experiment wäre mit Text und Titel zusammen.
Zählplots für beide Etiketten:
sns.countplot(x="label", data=news_d);
print("1: Unreliable")
print("0: Reliable")
print("Distribution of labels:")
print(news_d.label.value_counts());
Ausgabe:
1: Unreliable
0: Reliable
Distribution of labels:
1 10413
0 10387
Name: label, dtype: int64
print(round(news_d.label.value_counts(normalize=True),2)*100);
Ausgabe:
1 50.0
0 50.0
Name: label, dtype: float64
Die Anzahl der nicht vertrauenswürdigen Artikel (gefälscht oder 1) beträgt 10413, während die Anzahl der vertrauenswürdigen Artikel (zuverlässig oder 0) 10387 beträgt. Fast 50 % der Artikel sind gefälscht. Daher misst die Genauigkeitsmetrik, wie gut unser Modell beim Erstellen eines Klassifikators abschneidet.
In diesem Abschnitt werden wir unseren Datensatz bereinigen, um einige Analysen durchzuführen:
# Constants that are used to sanitize the datasets
column_n = ['id', 'title', 'author', 'text', 'label']
remove_c = ['id','author']
categorical_features = []
target_col = ['label']
text_f = ['title', 'text']
# Clean Datasets
import nltk
from nltk.corpus import stopwords
import re
from nltk.stem.porter import PorterStemmer
from collections import Counter
ps = PorterStemmer()
wnl = nltk.stem.WordNetLemmatizer()
stop_words = stopwords.words('english')
stopwords_dict = Counter(stop_words)
# Removed unused clumns
def remove_unused_c(df,column_n=remove_c):
df = df.drop(column_n,axis=1)
return df
# Impute null values with None
def null_process(feature_df):
for col in text_f:
feature_df.loc[feature_df[col].isnull(), col] = "None"
return feature_df
def clean_dataset(df):
# remove unused column
df = remove_unused_c(df)
#impute null values
df = null_process(df)
return df
# Cleaning text from unused characters
def clean_text(text):
text = str(text).replace(r'http[\w:/\.]+', ' ') # removing urls
text = str(text).replace(r'[^\.\w\s]', ' ') # remove everything but characters and punctuation
text = str(text).replace('[^a-zA-Z]', ' ')
text = str(text).replace(r'\s\s+', ' ')
text = text.lower().strip()
#text = ' '.join(text)
return text
## Nltk Preprocessing include:
# Stop words, Stemming and Lemmetization
# For our project we use only Stop word removal
def nltk_preprocess(text):
text = clean_text(text)
wordlist = re.sub(r'[^\w\s]', '', text).split()
#text = ' '.join([word for word in wordlist if word not in stopwords_dict])
#text = [ps.stem(word) for word in wordlist if not word in stopwords_dict]
text = ' '.join([wnl.lemmatize(word) for word in wordlist if word not in stopwords_dict])
return text
Im obigen Codeblock:
re
für Regex.nltk.corpus
. Bei der Arbeit mit Wörtern, insbesondere bei der Betrachtung der Semantik, müssen wir manchmal gebräuchliche Wörter eliminieren, die einer Aussage keine signifikante Bedeutung hinzufügen, wie z. B. "but"
, "can"
, "we"
, usw.PorterStemmer
wird verwendet, um Wortstämme mit NLTK auszuführen. Stemmer entfernen Wörter ihrer morphologischen Affixe und lassen nur den Wortstamm übrig.WordNetLemmatizer()
aus der NLTK-Bibliothek zur Lemmatisierung. Lemmatisierung ist viel effektiver als Stemmung . Es geht über die Wortreduktion hinaus und wertet das gesamte Lexikon einer Sprache aus, um eine morphologische Analyse auf Wörter anzuwenden, mit dem Ziel, nur Flexionsenden zu entfernen und die Basis- oder Wörterbuchform eines Wortes zurückzugeben, die als Lemma bekannt ist.stopwords.words('english')
Lassen Sie uns einen Blick auf die Liste aller englischen Stoppwörter werfen, die von NLTK unterstützt werden.remove_unused_c()
Funktion wird verwendet, um die unbenutzten Spalten zu entfernen.None
der Verwendung der null_process()
Funktion.clean_dataset()
rufen wir remove_unused_c()
und null_process()
Funktionen auf. Diese Funktion ist für die Datenbereinigung zuständig.clean_text()
Funktion erstellt.nltk_preprocess()
Funktion erstellt.Vorverarbeitung der text
und title
:
# Perform data cleaning on train and test dataset by calling clean_dataset function
df = clean_dataset(news_d)
# apply preprocessing on text through apply method by calling the function nltk_preprocess
df["text"] = df.text.apply(nltk_preprocess)
# apply preprocessing on title through apply method by calling the function nltk_preprocess
df["title"] = df.title.apply(nltk_preprocess)
# Dataset after cleaning and preprocessing step
df.head()
Ausgabe:
title text label
0 house dem aide didnt even see comeys letter ja... house dem aide didnt even see comeys letter ja... 1
1 flynn hillary clinton big woman campus breitbart ever get feeling life circle roundabout rather... 0
2 truth might get fired truth might get fired october 29 2016 tension ... 1
3 15 civilian killed single u airstrike identified video 15 civilian killed single u airstrike id... 1
4 iranian woman jailed fictional unpublished sto... print iranian woman sentenced six year prison ... 1
In diesem Abschnitt führen wir Folgendes durch:
Die häufigsten Wörter erscheinen fett und größer in einer Wortwolke. In diesem Abschnitt wird eine Wortwolke für alle Wörter im Datensatz erstellt.
Die Funktion der WordCloud - Bibliothek wordcloud()
wird verwendet, und die generate()
wird zum Generieren des Wortwolkenbildes verwendet:
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
# initialize the word cloud
wordcloud = WordCloud( background_color='black', width=800, height=600)
# generate the word cloud by passing the corpus
text_cloud = wordcloud.generate(' '.join(df['text']))
# plotting the word cloud
plt.figure(figsize=(20,30))
plt.imshow(text_cloud)
plt.axis('off')
plt.show()
Ausgabe:
Wortwolke nur für zuverlässige Nachrichten:
true_n = ' '.join(df[df['label']==0]['text'])
wc = wordcloud.generate(true_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
Ausgabe:
Wortwolke nur für Fake News:
fake_n = ' '.join(df[df['label']==1]['text'])
wc= wordcloud.generate(fake_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
Ausgabe:
Ein N-Gramm ist eine Folge von Buchstaben oder Wörtern. Ein Zeichen-Unigramm besteht aus einem einzelnen Zeichen, während ein Bigramm aus einer Reihe von zwei Zeichen besteht. In ähnlicher Weise bestehen Wort-N-Gramme aus einer Reihe von n Wörtern. Das Wort "united" ist ein 1-Gramm (Unigram). Die Kombination der Wörter "United State" ist ein 2-Gramm (Bigramm), "New York City" ist ein 3-Gramm.
Lassen Sie uns das häufigste Bigramm in den zuverlässigen Nachrichten darstellen:
def plot_top_ngrams(corpus, title, ylabel, xlabel="Number of Occurences", n=2):
"""Utility function to plot top n-grams"""
true_b = (pd.Series(nltk.ngrams(corpus.split(), n)).value_counts())[:20]
true_b.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
plt.show()
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Bigrams', "Bigram", n=2)
Das häufigste Bigramm in den Fake News:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Bigrams', "Bigram", n=2)
Das häufigste Trigramm bei zuverlässigen Nachrichten:
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Trigrams', "Trigrams", n=3)
Für Fake News jetzt:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Trigrams', "Trigrams", n=3)
Die obigen Diagramme geben uns einige Ideen, wie beide Klassen aussehen. Im nächsten Abschnitt verwenden wir die Transformers-Bibliothek , um einen Detektor für gefälschte Nachrichten zu erstellen.
In diesem Abschnitt wird ausgiebig Code aus dem BERT-Tutorial zur Feinabstimmung entnommen, um mithilfe der Transformers-Bibliothek einen Klassifikator für gefälschte Nachrichten zu erstellen. Für detailliertere Informationen können Sie also zum Original-Tutorial gehen .
Wenn Sie keine Transformatoren installiert haben, müssen Sie:
$ pip install transformers
Lassen Sie uns die erforderlichen Bibliotheken importieren:
import torch
from transformers.file_utils import is_tf_available, is_torch_available, is_torch_tpu_available
from transformers import BertTokenizerFast, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
import numpy as np
from sklearn.model_selection import train_test_split
import random
Wir wollen unsere Ergebnisse reproduzierbar machen, auch wenn wir unsere Umgebung neu starten:
def set_seed(seed: int):
"""
Helper function for reproducible behavior to set the seed in ``random``, ``numpy``, ``torch`` and/or ``tf`` (if
installed).
Args:
seed (:obj:`int`): The seed to set.
"""
random.seed(seed)
np.random.seed(seed)
if is_torch_available():
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
# ^^ safe to call this function even if cuda is not available
if is_tf_available():
import tensorflow as tf
tf.random.set_seed(seed)
set_seed(1)
Das Modell, das wir verwenden werden, ist das bert-base-uncased
:
# the model we gonna train, base uncased BERT
# check text classification models here: https://huggingface.co/models?filter=text-classification
model_name = "bert-base-uncased"
# max sequence length for each document/sentence sample
max_length = 512
Tokenizer laden:
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_name, do_lower_case=True)
Lassen Sie uns nun NaN
Werte aus den Spalten text
, author
und bereinigen:title
news_df = news_d[news_d['text'].notna()]
news_df = news_df[news_df["author"].notna()]
news_df = news_df[news_df["title"].notna()]
Erstellen Sie als Nächstes eine Funktion, die den Datensatz als Pandas-Datenrahmen nimmt und die Trainings-/Validierungsaufteilungen von Texten und Beschriftungen als Listen zurückgibt:
def prepare_data(df, test_size=0.2, include_title=True, include_author=True):
texts = []
labels = []
for i in range(len(df)):
text = df["text"].iloc[i]
label = df["label"].iloc[i]
if include_title:
text = df["title"].iloc[i] + " - " + text
if include_author:
text = df["author"].iloc[i] + " : " + text
if text and label in [0, 1]:
texts.append(text)
labels.append(label)
return train_test_split(texts, labels, test_size=test_size)
train_texts, valid_texts, train_labels, valid_labels = prepare_data(news_df)
Die obige Funktion nimmt den Datensatz in einem Datenrahmentyp und gibt sie als Listen zurück, die in Trainings- und Validierungssätze aufgeteilt sind. Die Einstellung include_title
auf True
bedeutet, dass wir die title
Spalte zu dem hinzufügen, die text
wir für das Training verwenden werden, die Einstellung include_author
auf bedeutet, dass wir auch die Spalte zum Text True
hinzufügen .author
Stellen wir sicher, dass die Beschriftungen und Texte die gleiche Länge haben:
print(len(train_texts), len(train_labels))
print(len(valid_texts), len(valid_labels))
Ausgabe:
14628 14628
3657 3657
Verwenden wir den BERT-Tokenizer, um unseren Datensatz zu tokenisieren:
# tokenize the dataset, truncate when passed `max_length`,
# and pad with 0's when less than `max_length`
train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=max_length)
valid_encodings = tokenizer(valid_texts, truncation=True, padding=True, max_length=max_length)
Konvertieren der Kodierungen in einen PyTorch-Datensatz:
class NewsGroupsDataset(torch.utils.data.Dataset):
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {k: torch.tensor(v[idx]) for k, v in self.encodings.items()}
item["labels"] = torch.tensor([self.labels[idx]])
return item
def __len__(self):
return len(self.labels)
# convert our tokenized data into a torch Dataset
train_dataset = NewsGroupsDataset(train_encodings, train_labels)
valid_dataset = NewsGroupsDataset(valid_encodings, valid_labels)
Wir werden verwenden BertForSequenceClassification
, um unser BERT-Transformatormodell zu laden:
# load the model
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)
Wir setzen num_labels
auf 2, da es sich um eine binäre Klassifikation handelt. Die folgende Funktion ist ein Rückruf, um die Genauigkeit für jeden Validierungsschritt zu berechnen:
from sklearn.metrics import accuracy_score
def compute_metrics(pred):
labels = pred.label_ids
preds = pred.predictions.argmax(-1)
# calculate accuracy using sklearn's function
acc = accuracy_score(labels, preds)
return {
'accuracy': acc,
}
Lassen Sie uns die Trainingsparameter initialisieren:
training_args = TrainingArguments(
output_dir='./results', # output directory
num_train_epochs=1, # total number of training epochs
per_device_train_batch_size=10, # batch size per device during training
per_device_eval_batch_size=20, # batch size for evaluation
warmup_steps=100, # number of warmup steps for learning rate scheduler
logging_dir='./logs', # directory for storing logs
load_best_model_at_end=True, # load the best model when finished training (default metric is loss)
# but you can specify `metric_for_best_model` argument to change to accuracy or other metric
logging_steps=200, # log & save weights each logging_steps
save_steps=200,
evaluation_strategy="steps", # evaluate each `logging_steps`
)
Ich habe den per_device_train_batch_size
auf 10 eingestellt, aber Sie sollten ihn so hoch einstellen, wie Ihre GPU möglicherweise passen könnte. Setzen Sie logging_steps
und save_steps
auf 200, was bedeutet, dass wir eine Bewertung durchführen und die Modellgewichte bei jedem 200-Trainingsschritt speichern.
Auf dieser Seite finden Sie detailliertere Informationen zu den verfügbaren Trainingsparametern.
Lassen Sie uns den Trainer instanziieren:
trainer = Trainer(
model=model, # the instantiated Transformers model to be trained
args=training_args, # training arguments, defined above
train_dataset=train_dataset, # training dataset
eval_dataset=valid_dataset, # evaluation dataset
compute_metrics=compute_metrics, # the callback that computes metrics of interest
)
Training des Modells:
# train the model
trainer.train()
Das Training dauert je nach GPU einige Stunden. Wenn Sie die kostenlose Version von Colab verwenden, sollte es mit NVIDIA Tesla K80 eine Stunde dauern. Hier ist die Ausgabe:
***** Running training *****
Num examples = 14628
Num Epochs = 1
Instantaneous batch size per device = 10
Total train batch size (w. parallel, distributed & accumulation) = 10
Gradient Accumulation steps = 1
Total optimization steps = 1463
[1463/1463 41:07, Epoch 1/1]
Step Training Loss Validation Loss Accuracy
200 0.250800 0.100533 0.983867
400 0.027600 0.043009 0.993437
600 0.023400 0.017812 0.997539
800 0.014900 0.030269 0.994258
1000 0.022400 0.012961 0.998086
1200 0.009800 0.010561 0.998633
1400 0.007700 0.010300 0.998633
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-200
Configuration saved in ./results/checkpoint-200/config.json
Model weights saved in ./results/checkpoint-200/pytorch_model.bin
<SNIPPED>
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-1400
Configuration saved in ./results/checkpoint-1400/config.json
Model weights saved in ./results/checkpoint-1400/pytorch_model.bin
Training completed. Do not forget to share your model on huggingface.co/models =)
Loading best model from ./results/checkpoint-1400 (score: 0.010299865156412125).
TrainOutput(global_step=1463, training_loss=0.04888018785440506, metrics={'train_runtime': 2469.1722, 'train_samples_per_second': 5.924, 'train_steps_per_second': 0.593, 'total_flos': 3848788517806080.0, 'train_loss': 0.04888018785440506, 'epoch': 1.0})
Da load_best_model_at_end
auf eingestellt ist, True
werden nach Abschluss des Trainings die besten Gewichte geladen. Lassen Sie es uns mit unserem Validierungsset auswerten:
# evaluate the current model after training
trainer.evaluate()
Ausgabe:
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
[183/183 02:11]
{'epoch': 1.0,
'eval_accuracy': 0.998632759092152,
'eval_loss': 0.010299865156412125,
'eval_runtime': 132.0374,
'eval_samples_per_second': 27.697,
'eval_steps_per_second': 1.386}
Speichern des Modells und des Tokenizers:
# saving the fine tuned model & tokenizer
model_path = "fake-news-bert-base-uncased"
model.save_pretrained(model_path)
tokenizer.save_pretrained(model_path)
Nach dem Ausführen der obigen Zelle wird ein neuer Ordner mit der Modellkonfiguration und den Gewichten angezeigt. Wenn Sie eine Vorhersage durchführen möchten, verwenden Sie einfach die from_pretrained()
Methode, die wir beim Laden des Modells verwendet haben, und Sie können loslegen.
Als nächstes erstellen wir eine Funktion, die den Artikeltext als Argument akzeptiert und zurückgibt, ob er gefälscht ist oder nicht:
def get_prediction(text, convert_to_label=False):
# prepare our text into tokenized sequence
inputs = tokenizer(text, padding=True, truncation=True, max_length=max_length, return_tensors="pt").to("cuda")
# perform inference to our model
outputs = model(**inputs)
# get output probabilities by doing softmax
probs = outputs[0].softmax(1)
# executing argmax function to get the candidate label
d = {
0: "reliable",
1: "fake"
}
if convert_to_label:
return d[int(probs.argmax())]
else:
return int(probs.argmax())
Ich habe ein Beispiel dafür genommen test.csv
, dass das Modell nie eine Inferenz durchgeführt hat, ich habe es überprüft, und es ist ein aktueller Artikel aus der New York Times:
real_news = """
Tim Tebow Will Attempt Another Comeback, This Time in Baseball - The New York Times",Daniel Victor,"If at first you don’t succeed, try a different sport. Tim Tebow, who was a Heisman quarterback at the University of Florida but was unable to hold an N. F. L. job, is pursuing a career in Major League Baseball. <SNIPPED>
"""
Der Originaltext befindet sich in der Colab-Umgebung , wenn Sie ihn kopieren möchten, da es sich um einen vollständigen Artikel handelt. Übergeben wir es an das Modell und sehen uns die Ergebnisse an:
get_prediction(real_news, convert_to_label=True)
Ausgabe:
reliable
In diesem Abschnitt werden wir alle Artikel vorhersagen test.csv
, um eine Einreichungsdatei zu erstellen, um unsere Genauigkeit im Testsatz des Kaggle-Wettbewerbs zu sehen :
# read the test set
test_df = pd.read_csv("test.csv")
# make a copy of the testing set
new_df = test_df.copy()
# add a new column that contains the author, title and article content
new_df["new_text"] = new_df["author"].astype(str) + " : " + new_df["title"].astype(str) + " - " + new_df["text"].astype(str)
# get the prediction of all the test set
new_df["label"] = new_df["new_text"].apply(get_prediction)
# make the submission file
final_df = new_df[["id", "label"]]
final_df.to_csv("submit_final.csv", index=False)
Nachdem wir Autor, Titel und Artikeltext miteinander verkettet haben, übergeben wir die get_prediction()
Funktion an die neue Spalte, um die Spalte zu füllen label
, und verwenden dann die to_csv()
Methode, um die Übermittlungsdatei für Kaggle zu erstellen. Hier ist mein Submission Score:
Wir haben eine Genauigkeit von 99,78 % und 100 % auf privaten und öffentlichen Bestenlisten. Das ist großartig!
Okay, wir sind mit dem Tutorial fertig. Sie können diese Seite überprüfen , um verschiedene Trainingsparameter zu sehen, die Sie optimieren können.
Wenn Sie einen benutzerdefinierten Fake-News-Datensatz zur Feinabstimmung haben, müssen Sie einfach eine Liste von Beispielen an den Tokenizer übergeben, wie wir es getan haben, Sie werden danach keinen anderen Code mehr ändern.
Sehen Sie sich den vollständigen Code hier oder die Colab - Umgebung hier an .
1646044200
偽のニュースデータセットを探索し、ワードクラウドやngramなどのデータ分析を実行し、トランスフォーマーライブラリを使用してPythonで偽のニュース検出器を構築するためにBERTトランスフォーマーを微調整します。
フェイクニュースとは、虚偽または誤解を招くような主張をニュースとして意図的に放送することであり、その発言は意図的に欺瞞的です。
新聞、タブロイド紙、雑誌は、デジタルニュースプラットフォーム、ブログ、ソーシャルメディアフィード、および多数のモバイルニュースアプリケーションに取って代わられています。ニュース組織は、加入者に最新の情報を提供することにより、ソーシャルメディアとモバイルプラットフォームの使用の増加から恩恵を受けました。
消費者は現在、最新ニュースに即座にアクセスできます。これらのデジタルメディアプラットフォームは、世界の他の地域との接続が容易であるために注目を集めており、ユーザーは、民主主義、教育、健康、研究、歴史などのアイデアや討論トピックについて話し合い、共有することができます。デジタルプラットフォーム上の偽のニュースアイテムはますます人気が高まっており、政治的および経済的利益などの利益のために使用されています。
インターネット、ソーシャルメディア、デジタルプラットフォームが広く使用されているため、誰もが不正確で偏った情報を広める可能性があります。フェイクニュースの拡散を防ぐことはほとんど不可能です。虚偽のニュースの配信は急増しています。これは、政治などの1つのセクターに限定されるものではなく、スポーツ、健康、歴史、娯楽、科学と研究などが含まれます。
虚偽のニュースと正確なニュースを認識して区別することが重要です。1つの方法は、専門家にすべての情報を決定して事実を確認させることですが、これには時間がかかり、共有できない専門知識が必要です。次に、機械学習と人工知能ツールを使用して、偽のニュースの識別を自動化できます。
オンラインニュース情報には、さまざまな非構造化形式のデータ(ドキュメント、ビデオ、オーディオなど)が含まれますが、ここではテキスト形式のニュースに焦点を当てます。機械学習と自然言語処理の進歩により、記事やステートメントの誤解を招くような誤った性格を認識できるようになりました。
すべての媒体で偽のニュースを検出するために、いくつかの調査と実験が行われています。
このチュートリアルの主な目標は次のとおりです。
コンテンツの表は次のとおりです。
この作業では、Kaggleのフェイクニュースデータセットを利用して、信頼できないニュース記事をフェイクニュースとして分類しました。次の特性を含む完全なトレーニングデータセットがあります。
id
:ニュース記事の一意のIDtitle
:ニュース記事のタイトルauthor
:ニュース記事の著者text
:記事のテキスト; 不完全である可能性がありますlabel
:1(信頼できないまたは偽物)または0(信頼できる)で示される、信頼できない可能性のあるものとして記事をマークするラベル。これは、特定のニュース記事が信頼できるかどうかを予測する必要があるバイナリ分類の問題です。
Kaggleアカウントをお持ちの場合は、そこにあるWebサイトからデータセットをダウンロードして、ZIPファイルを抽出するだけです。
また、データセットをGoogleドライブにアップロードしました。ここで取得するか、ライブラリを使用してgdown
GoogleColabまたはJupyterノートブックに自動的にダウンロードできます。
$ pip install gdown
# download from Google Drive
$ gdown "https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t"
Downloading...
From: https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t
To: /content/fake-news.zip
100% 48.7M/48.7M [00:00<00:00, 74.6MB/s]
ファイルを解凍します。
$ unzip fake-news.zip
現在の作業ディレクトリには、、、、の3つのファイルが表示されtrain.csv
ます。これはtest.csv
、ほとんどのチュートリアルでsubmit.csv
使用します。train.csv
必要な依存関係のインストール:
$ pip install transformers nltk pandas numpy matplotlib seaborn wordcloud
注:ローカル環境にいる場合は、必ずPyTorch for GPUをインストールしてください。適切にインストールするには、このページにアクセスしてください。
分析に不可欠なライブラリをインポートしましょう。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
NLTKコーパスとモジュールは、標準のNLTKダウンローダーを使用してインストールする必要があります。
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
フェイクニュースデータセットは、さまざまな著者のオリジナルおよび架空の記事のタイトルとテキストで構成されています。データセットをインポートしましょう:
# load the dataset
news_d = pd.read_csv("train.csv")
print("Shape of News data:", news_d.shape)
print("News data columns", news_d.columns)
出力:
Shape of News data: (20800, 5)
News data columns Index(['id', 'title', 'author', 'text', 'label'], dtype='object')
データセットは次のようになります。
# by using df.head(), we can immediately familiarize ourselves with the dataset.
news_d.head()
出力:
id title author text label
0 0 House Dem Aide: We Didn’t Even See Comey’s Let... Darrell Lucus House Dem Aide: We Didn’t Even See Comey’s Let... 1
1 1 FLYNN: Hillary Clinton, Big Woman on Campus - ... Daniel J. Flynn Ever get the feeling your life circles the rou... 0
2 2 Why the Truth Might Get You Fired Consortiumnews.com Why the Truth Might Get You Fired October 29, ... 1
3 3 15 Civilians Killed In Single US Airstrike Hav... Jessica Purkiss Videos 15 Civilians Killed In Single US Airstr... 1
4 4 Iranian woman jailed for fictional unpublished... Howard Portnoy Print \nAn Iranian woman has been sentenced to... 1
20,800行あり、5列あります。text
列のいくつかの統計を見てみましょう:
#Text Word startistics: min.mean, max and interquartile range
txt_length = news_d.text.str.split().str.len()
txt_length.describe()
出力:
count 20761.000000
mean 760.308126
std 869.525988
min 0.000000
25% 269.000000
50% 556.000000
75% 1052.000000
max 24234.000000
Name: text, dtype: float64
title
列の統計:
#Title statistics
title_length = news_d.title.str.split().str.len()
title_length.describe()
出力:
count 20242.000000
mean 12.420709
std 4.098735
min 1.000000
25% 10.000000
50% 13.000000
75% 15.000000
max 72.000000
Name: title, dtype: float64
トレーニングセットとテストセットの統計は次のとおりです。
text
属性の単語数は多く、平均760語で、75%が1000語を超えています。title
属性は平均12語の短いステートメントであり、そのうちの75%は約15語です。私たちの実験は、テキストとタイトルの両方を一緒に使用することです。
両方のラベルのプロットを数える:
sns.countplot(x="label", data=news_d);
print("1: Unreliable")
print("0: Reliable")
print("Distribution of labels:")
print(news_d.label.value_counts());
出力:
1: Unreliable
0: Reliable
Distribution of labels:
1 10413
0 10387
Name: label, dtype: int64
print(round(news_d.label.value_counts(normalize=True),2)*100);
出力:
1 50.0
0 50.0
Name: label, dtype: float64
信頼できない記事(偽物または1)の数は10413であり、信頼できる記事(信頼できるまたは0)の数は10387です。記事のほぼ50%は偽物です。したがって、精度メトリックは、分類器を構築するときにモデルがどの程度うまく機能しているかを測定します。
このセクションでは、データセットをクリーンアップして分析を行います。
# Constants that are used to sanitize the datasets
column_n = ['id', 'title', 'author', 'text', 'label']
remove_c = ['id','author']
categorical_features = []
target_col = ['label']
text_f = ['title', 'text']
# Clean Datasets
import nltk
from nltk.corpus import stopwords
import re
from nltk.stem.porter import PorterStemmer
from collections import Counter
ps = PorterStemmer()
wnl = nltk.stem.WordNetLemmatizer()
stop_words = stopwords.words('english')
stopwords_dict = Counter(stop_words)
# Removed unused clumns
def remove_unused_c(df,column_n=remove_c):
df = df.drop(column_n,axis=1)
return df
# Impute null values with None
def null_process(feature_df):
for col in text_f:
feature_df.loc[feature_df[col].isnull(), col] = "None"
return feature_df
def clean_dataset(df):
# remove unused column
df = remove_unused_c(df)
#impute null values
df = null_process(df)
return df
# Cleaning text from unused characters
def clean_text(text):
text = str(text).replace(r'http[\w:/\.]+', ' ') # removing urls
text = str(text).replace(r'[^\.\w\s]', ' ') # remove everything but characters and punctuation
text = str(text).replace('[^a-zA-Z]', ' ')
text = str(text).replace(r'\s\s+', ' ')
text = text.lower().strip()
#text = ' '.join(text)
return text
## Nltk Preprocessing include:
# Stop words, Stemming and Lemmetization
# For our project we use only Stop word removal
def nltk_preprocess(text):
text = clean_text(text)
wordlist = re.sub(r'[^\w\s]', '', text).split()
#text = ' '.join([word for word in wordlist if word not in stopwords_dict])
#text = [ps.stem(word) for word in wordlist if not word in stopwords_dict]
text = ' '.join([wnl.lemmatize(word) for word in wordlist if word not in stopwords_dict])
return text
上記のコードブロック:
re
正規表現をインポートします。nltk.corpus
ます。単語を扱うとき、特にセマンティクスを検討するときは、、、、など"but"
、ステートメントに重要な意味を追加しない一般的な単語を削除する必要がある場合があります。"can""we"
PorterStemmer
NLTKでステミングワードを実行するために使用されます。ステマーは、形態学的接辞の単語を取り除き、単語の語幹のみを残します。WordNetLemmatizer()
レンマ化のためにNLTKライブラリからインポートします。Lemmatizationはステミングよりもはるかに効果的です。これは、単語の削減を超えて、言語の語彙全体を評価し、語形変化の終わりを削除して、見出語として知られる単語のベースまたは辞書形式を返すことを目的として、形態素解析を単語に適用します。stopwords.words('english')
NLTKでサポートされているすべての英語のストップワードのリストを見てみましょう。remove_unused_c()
関数は、未使用の列を削除するために使用されます。None
関数を使用してnull値を代入しますnull_process()
。clean_dataset()
呼び出します。この関数は、データのクリーニングを担当します。remove_unused_c()null_process()
clean_text()
関数を作成しました。nltk_preprocess()
そのための関数を作成しました。text
およびの前処理title
:
# Perform data cleaning on train and test dataset by calling clean_dataset function
df = clean_dataset(news_d)
# apply preprocessing on text through apply method by calling the function nltk_preprocess
df["text"] = df.text.apply(nltk_preprocess)
# apply preprocessing on title through apply method by calling the function nltk_preprocess
df["title"] = df.title.apply(nltk_preprocess)
# Dataset after cleaning and preprocessing step
df.head()
出力:
title text label
0 house dem aide didnt even see comeys letter ja... house dem aide didnt even see comeys letter ja... 1
1 flynn hillary clinton big woman campus breitbart ever get feeling life circle roundabout rather... 0
2 truth might get fired truth might get fired october 29 2016 tension ... 1
3 15 civilian killed single u airstrike identified video 15 civilian killed single u airstrike id... 1
4 iranian woman jailed fictional unpublished sto... print iranian woman sentenced six year prison ... 1
このセクションでは、以下を実行します。
最も頻繁に使用される単語は、ワードクラウド内で太字の大きなフォントで表示されます。このセクションでは、データセット内のすべての単語に対してワードクラウドを実行します。
WordCloudライブラリのwordcloud()
関数が使用され、ワードgenerate()
クラウドイメージの生成に使用されます。
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
# initialize the word cloud
wordcloud = WordCloud( background_color='black', width=800, height=600)
# generate the word cloud by passing the corpus
text_cloud = wordcloud.generate(' '.join(df['text']))
# plotting the word cloud
plt.figure(figsize=(20,30))
plt.imshow(text_cloud)
plt.axis('off')
plt.show()
出力:
信頼できるニュース専用のワードクラウド:
true_n = ' '.join(df[df['label']==0]['text'])
wc = wordcloud.generate(true_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
出力:
フェイクニュース専用のワードクラウド:
fake_n = ' '.join(df[df['label']==1]['text'])
wc= wordcloud.generate(fake_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
出力:
N-gramは、文字または単語のシーケンスです。文字ユニグラムは1つの文字で構成され、バイグラムは一連の2文字で構成されます。同様に、単語N-gramは一連のn個の単語で構成されます。「団結」という言葉は1グラム(ユニグラム)です。「米国」という言葉の組み合わせは2グラム(バイグラム)、「ニューヨーク市」は3グラムです。
信頼できるニュースで最も一般的なバイグラムをプロットしてみましょう。
def plot_top_ngrams(corpus, title, ylabel, xlabel="Number of Occurences", n=2):
"""Utility function to plot top n-grams"""
true_b = (pd.Series(nltk.ngrams(corpus.split(), n)).value_counts())[:20]
true_b.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
plt.show()
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Bigrams', "Bigram", n=2)
フェイクニュースで最も一般的なバイグラム:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Bigrams', "Bigram", n=2)
信頼できるニュースに関する最も一般的なトリグラム:
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Trigrams', "Trigrams", n=3)
今のフェイクニュースの場合:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Trigrams', "Trigrams", n=3)
上記のプロットは、両方のクラスがどのように見えるかについてのいくつかのアイデアを示しています。次のセクションでは、トランスフォーマーライブラリを使用して偽のニュース検出器を構築します。
このセクションでは、トランスフォーマーライブラリを使用して偽のニュース分類子を作成するために、BERTチュートリアルの微調整からコードを広範囲に取得します。したがって、より詳細な情報については、元のチュートリアルに進むことができます。
トランスフォーマーをインストールしなかった場合は、次のことを行う必要があります。
$ pip install transformers
必要なライブラリをインポートしましょう:
import torch
from transformers.file_utils import is_tf_available, is_torch_available, is_torch_tpu_available
from transformers import BertTokenizerFast, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
import numpy as np
from sklearn.model_selection import train_test_split
import random
環境を再起動しても、結果を再現可能にしたいと考えています。
def set_seed(seed: int):
"""
Helper function for reproducible behavior to set the seed in ``random``, ``numpy``, ``torch`` and/or ``tf`` (if
installed).
Args:
seed (:obj:`int`): The seed to set.
"""
random.seed(seed)
np.random.seed(seed)
if is_torch_available():
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
# ^^ safe to call this function even if cuda is not available
if is_tf_available():
import tensorflow as tf
tf.random.set_seed(seed)
set_seed(1)
使用するモデルは次のbert-base-uncased
とおりです。
# the model we gonna train, base uncased BERT
# check text classification models here: https://huggingface.co/models?filter=text-classification
model_name = "bert-base-uncased"
# max sequence length for each document/sentence sample
max_length = 512
トークナイザーのロード:
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_name, do_lower_case=True)
次に、、、および列NaN
から値をクリーンアップしましょう。textauthortitle
news_df = news_d[news_d['text'].notna()]
news_df = news_df[news_df["author"].notna()]
news_df = news_df[news_df["title"].notna()]
次に、データセットをPandasデータフレームとして受け取り、テキストとラベルのトレイン/検証分割をリストとして返す関数を作成します。
def prepare_data(df, test_size=0.2, include_title=True, include_author=True):
texts = []
labels = []
for i in range(len(df)):
text = df["text"].iloc[i]
label = df["label"].iloc[i]
if include_title:
text = df["title"].iloc[i] + " - " + text
if include_author:
text = df["author"].iloc[i] + " : " + text
if text and label in [0, 1]:
texts.append(text)
labels.append(label)
return train_test_split(texts, labels, test_size=test_size)
train_texts, valid_texts, train_labels, valid_labels = prepare_data(news_df)
上記の関数は、データフレームタイプのデータセットを取得し、トレーニングセットと検証セットに分割されたリストとしてそれらを返します。に設定include_title
すると、トレーニングに使用する列に列がTrue
追加されます。に設定すると、テキストにも列が追加されます。titletextinclude_authorTrueauthor
ラベルとテキストの長さが同じであることを確認しましょう。
print(len(train_texts), len(train_labels))
print(len(valid_texts), len(valid_labels))
出力:
14628 14628
3657 3657
BERTトークナイザーを使用して、データセットをトークン化してみましょう。
# tokenize the dataset, truncate when passed `max_length`,
# and pad with 0's when less than `max_length`
train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=max_length)
valid_encodings = tokenizer(valid_texts, truncation=True, padding=True, max_length=max_length)
エンコーディングをPyTorchデータセットに変換します。
class NewsGroupsDataset(torch.utils.data.Dataset):
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {k: torch.tensor(v[idx]) for k, v in self.encodings.items()}
item["labels"] = torch.tensor([self.labels[idx]])
return item
def __len__(self):
return len(self.labels)
# convert our tokenized data into a torch Dataset
train_dataset = NewsGroupsDataset(train_encodings, train_labels)
valid_dataset = NewsGroupsDataset(valid_encodings, valid_labels)
BertForSequenceClassification
BERTトランスフォーマーモデルのロードに使用します。
# load the model
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)
num_labels
二項分類なので2に設定します。以下の関数は、各検証ステップの精度を計算するためのコールバックです。
from sklearn.metrics import accuracy_score
def compute_metrics(pred):
labels = pred.label_ids
preds = pred.predictions.argmax(-1)
# calculate accuracy using sklearn's function
acc = accuracy_score(labels, preds)
return {
'accuracy': acc,
}
トレーニングパラメータを初期化しましょう:
training_args = TrainingArguments(
output_dir='./results', # output directory
num_train_epochs=1, # total number of training epochs
per_device_train_batch_size=10, # batch size per device during training
per_device_eval_batch_size=20, # batch size for evaluation
warmup_steps=100, # number of warmup steps for learning rate scheduler
logging_dir='./logs', # directory for storing logs
load_best_model_at_end=True, # load the best model when finished training (default metric is loss)
# but you can specify `metric_for_best_model` argument to change to accuracy or other metric
logging_steps=200, # log & save weights each logging_steps
save_steps=200,
evaluation_strategy="steps", # evaluate each `logging_steps`
)
を10に設定しましたper_device_train_batch_size
が、GPUが収まる限り高く設定する必要があります。logging_steps
andを200に設定しsave_steps
ます。これは、評価を実行し、200のトレーニングステップごとにモデルの重みを保存することを意味します。
利用可能なトレーニングパラメータの詳細については、このページを確認 してください。
トレーナーをインスタンス化しましょう:
trainer = Trainer(
model=model, # the instantiated Transformers model to be trained
args=training_args, # training arguments, defined above
train_dataset=train_dataset, # training dataset
eval_dataset=valid_dataset, # evaluation dataset
compute_metrics=compute_metrics, # the callback that computes metrics of interest
)
モデルのトレーニング:
# train the model
trainer.train()
GPUによっては、トレーニングが完了するまでに数時間かかります。Colabの無料バージョンを使用している場合は、NVIDIA TeslaK80で1時間かかるはずです。出力は次のとおりです。
***** Running training *****
Num examples = 14628
Num Epochs = 1
Instantaneous batch size per device = 10
Total train batch size (w. parallel, distributed & accumulation) = 10
Gradient Accumulation steps = 1
Total optimization steps = 1463
[1463/1463 41:07, Epoch 1/1]
Step Training Loss Validation Loss Accuracy
200 0.250800 0.100533 0.983867
400 0.027600 0.043009 0.993437
600 0.023400 0.017812 0.997539
800 0.014900 0.030269 0.994258
1000 0.022400 0.012961 0.998086
1200 0.009800 0.010561 0.998633
1400 0.007700 0.010300 0.998633
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-200
Configuration saved in ./results/checkpoint-200/config.json
Model weights saved in ./results/checkpoint-200/pytorch_model.bin
<SNIPPED>
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-1400
Configuration saved in ./results/checkpoint-1400/config.json
Model weights saved in ./results/checkpoint-1400/pytorch_model.bin
Training completed. Do not forget to share your model on huggingface.co/models =)
Loading best model from ./results/checkpoint-1400 (score: 0.010299865156412125).
TrainOutput(global_step=1463, training_loss=0.04888018785440506, metrics={'train_runtime': 2469.1722, 'train_samples_per_second': 5.924, 'train_steps_per_second': 0.593, 'total_flos': 3848788517806080.0, 'train_loss': 0.04888018785440506, 'epoch': 1.0})
load_best_model_at_end
に設定されているためTrue
、トレーニングが完了すると、最適なウェイトがロードされます。検証セットを使用して評価してみましょう。
# evaluate the current model after training
trainer.evaluate()
出力:
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
[183/183 02:11]
{'epoch': 1.0,
'eval_accuracy': 0.998632759092152,
'eval_loss': 0.010299865156412125,
'eval_runtime': 132.0374,
'eval_samples_per_second': 27.697,
'eval_steps_per_second': 1.386}
モデルとトークナイザーの保存:
# saving the fine tuned model & tokenizer
model_path = "fake-news-bert-base-uncased"
model.save_pretrained(model_path)
tokenizer.save_pretrained(model_path)
上記のセルを実行すると、モデルの構成と重みを含む新しいフォルダーが表示されます。予測を実行するfrom_pretrained()
場合は、モデルをロードしたときに使用した方法を使用するだけで、準備は完了です。
次に、記事のテキストを引数として受け取り、それが偽物であるかどうかを返す関数を作成しましょう。
def get_prediction(text, convert_to_label=False):
# prepare our text into tokenized sequence
inputs = tokenizer(text, padding=True, truncation=True, max_length=max_length, return_tensors="pt").to("cuda")
# perform inference to our model
outputs = model(**inputs)
# get output probabilities by doing softmax
probs = outputs[0].softmax(1)
# executing argmax function to get the candidate label
d = {
0: "reliable",
1: "fake"
}
if convert_to_label:
return d[int(probs.argmax())]
else:
return int(probs.argmax())
モデルが推論を実行するのを見たことがないという例を取り上げ、test.csv
それを確認しました。これは、ニューヨークタイムズの実際の記事です。
real_news = """
Tim Tebow Will Attempt Another Comeback, This Time in Baseball - The New York Times",Daniel Victor,"If at first you don’t succeed, try a different sport. Tim Tebow, who was a Heisman quarterback at the University of Florida but was unable to hold an N. F. L. job, is pursuing a career in Major League Baseball. <SNIPPED>
"""
元のテキストは完全な記事であるため、コピーする場合はColab環境にあります。それをモデルに渡して、結果を見てみましょう。
get_prediction(real_news, convert_to_label=True)
出力:
reliable
このセクションでは、のすべての記事を予測しtest.csv
て提出ファイルを作成し、Kaggleコンテストのテストセットでの正確性を確認します。
# read the test set
test_df = pd.read_csv("test.csv")
# make a copy of the testing set
new_df = test_df.copy()
# add a new column that contains the author, title and article content
new_df["new_text"] = new_df["author"].astype(str) + " : " + new_df["title"].astype(str) + " - " + new_df["text"].astype(str)
# get the prediction of all the test set
new_df["label"] = new_df["new_text"].apply(get_prediction)
# make the submission file
final_df = new_df[["id", "label"]]
final_df.to_csv("submit_final.csv", index=False)
著者、タイトル、記事のテキストを連結した後、get_prediction()
関数を新しい列に渡して列を埋め、メソッドをlabel
使用to_csv()
してKaggleの送信ファイルを作成します。これが私の提出スコアです:
プライベートおよびパブリックのリーダーボードで99.78%および100%の精度が得られました。すごい!
了解しました。チュートリアルは終了です。このページをチェックして、微調整できるさまざまなトレーニングパラメータを確認できます。
微調整用のカスタムのフェイクニュースデータセットがある場合は、サンプルのリストをトークン化ツールに渡すだけで済みます。その後、他のコードを変更することはありません。
1646055360
Explorar el conjunto de datos de noticias falsas, realizar análisis de datos como nubes de palabras y ngramas, y ajustar el transformador BERT para construir un detector de noticias falsas en Python usando la biblioteca de transformadores.
Las noticias falsas son la transmisión intencional de afirmaciones falsas o engañosas como noticias, donde las declaraciones son deliberadamente engañosas.
Los periódicos, tabloides y revistas han sido reemplazados por plataformas de noticias digitales, blogs, fuentes de redes sociales y una plétora de aplicaciones de noticias móviles. Las organizaciones de noticias se beneficiaron del mayor uso de las redes sociales y las plataformas móviles al proporcionar a los suscriptores información actualizada al minuto.
Los consumidores ahora tienen acceso instantáneo a las últimas noticias. Estas plataformas de medios digitales han aumentado en importancia debido a su fácil conexión con el resto del mundo y permiten a los usuarios discutir y compartir ideas y debatir temas como la democracia, la educación, la salud, la investigación y la historia. Las noticias falsas en las plataformas digitales son cada vez más populares y se utilizan con fines de lucro, como ganancias políticas y financieras.
Debido a que Internet, las redes sociales y las plataformas digitales son ampliamente utilizadas, cualquiera puede propagar información inexacta y sesgada. Es casi imposible evitar la difusión de noticias falsas. Hay un aumento tremendo en la distribución de noticias falsas, que no se restringe a un sector como la política sino que incluye deportes, salud, historia, entretenimiento y ciencia e investigación.
Es vital reconocer y diferenciar entre noticias falsas y veraces. Un método es hacer que un experto decida y verifique cada pieza de información, pero esto lleva tiempo y requiere experiencia que no se puede compartir. En segundo lugar, podemos utilizar herramientas de aprendizaje automático e inteligencia artificial para automatizar la identificación de noticias falsas.
La información de noticias en línea incluye varios datos en formato no estructurado (como documentos, videos y audio), pero aquí nos concentraremos en las noticias en formato de texto. Con el progreso del aprendizaje automático y el procesamiento del lenguaje natural , ahora podemos reconocer el carácter engañoso y falso de un artículo o declaración.
Se están realizando varios estudios y experimentos para detectar noticias falsas en todos los medios.
Nuestro objetivo principal de este tutorial es:
Aquí está la tabla de contenido:
En este trabajo, utilizamos el conjunto de datos de noticias falsas de Kaggle para clasificar artículos de noticias no confiables como noticias falsas. Disponemos de un completo dataset de entrenamiento que contiene las siguientes características:
id
: identificación única para un artículo de noticiastitle
: título de un artículo periodísticoauthor
: autor de la noticiatext
: texto del artículo; podría estar incompletolabel
: una etiqueta que marca el artículo como potencialmente no confiable denotado por 1 (poco confiable o falso) o 0 (confiable).Es un problema de clasificación binaria en el que debemos predecir si una determinada noticia es fiable o no.
Si tiene una cuenta de Kaggle, simplemente puede descargar el conjunto de datos del sitio web y extraer el archivo ZIP.
También cargué el conjunto de datos en Google Drive y puede obtenerlo aquí o usar la gdown
biblioteca para descargarlo automáticamente en Google Colab o cuadernos de Jupyter:
$ pip install gdown
# download from Google Drive
$ gdown "https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t"
Downloading...
From: https://drive.google.com/uc?id=178f_VkNxccNidap-5-uffXUW475pAuPy&confirm=t
To: /content/fake-news.zip
100% 48.7M/48.7M [00:00<00:00, 74.6MB/s]
Descomprimiendo los archivos:
$ unzip fake-news.zip
Aparecerán tres archivos en el directorio de trabajo actual: train.csv
, test.csv
y submit.csv
, que usaremos train.csv
en la mayor parte del tutorial.
Instalando las dependencias requeridas:
$ pip install transformers nltk pandas numpy matplotlib seaborn wordcloud
Nota: si se encuentra en un entorno local, asegúrese de instalar PyTorch para GPU, diríjase a esta página para una instalación adecuada.
Importemos las bibliotecas esenciales para el análisis:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
El corpus y los módulos NLTK deben instalarse mediante el descargador NLTK estándar:
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
El conjunto de datos de noticias falsas comprende títulos y textos de artículos originales y ficticios de varios autores. Importemos nuestro conjunto de datos:
# load the dataset
news_d = pd.read_csv("train.csv")
print("Shape of News data:", news_d.shape)
print("News data columns", news_d.columns)
Producción:
Shape of News data: (20800, 5)
News data columns Index(['id', 'title', 'author', 'text', 'label'], dtype='object')
Así es como se ve el conjunto de datos:
# by using df.head(), we can immediately familiarize ourselves with the dataset.
news_d.head()
Producción:
id title author text label
0 0 House Dem Aide: We Didn’t Even See Comey’s Let... Darrell Lucus House Dem Aide: We Didn’t Even See Comey’s Let... 1
1 1 FLYNN: Hillary Clinton, Big Woman on Campus - ... Daniel J. Flynn Ever get the feeling your life circles the rou... 0
2 2 Why the Truth Might Get You Fired Consortiumnews.com Why the Truth Might Get You Fired October 29, ... 1
3 3 15 Civilians Killed In Single US Airstrike Hav... Jessica Purkiss Videos 15 Civilians Killed In Single US Airstr... 1
4 4 Iranian woman jailed for fictional unpublished... Howard Portnoy Print \nAn Iranian woman has been sentenced to... 1
Tenemos 20.800 filas, que tienen cinco columnas. Veamos algunas estadísticas de la text
columna:
#Text Word startistics: min.mean, max and interquartile range
txt_length = news_d.text.str.split().str.len()
txt_length.describe()
Producción:
count 20761.000000
mean 760.308126
std 869.525988
min 0.000000
25% 269.000000
50% 556.000000
75% 1052.000000
max 24234.000000
Name: text, dtype: float64
Estadísticas de la title
columna:
#Title statistics
title_length = news_d.title.str.split().str.len()
title_length.describe()
Producción:
count 20242.000000
mean 12.420709
std 4.098735
min 1.000000
25% 10.000000
50% 13.000000
75% 15.000000
max 72.000000
Name: title, dtype: float64
Las estadísticas para los conjuntos de entrenamiento y prueba son las siguientes:
text
atributo tiene un conteo de palabras más alto con un promedio de 760 palabras y un 75% con más de 1000 palabras.title
atributo es una declaración breve con un promedio de 12 palabras, y el 75% de ellas tiene alrededor de 15 palabras.Nuestro experimento sería con el texto y el título juntos.
Parcelas de conteo para ambas etiquetas:
sns.countplot(x="label", data=news_d);
print("1: Unreliable")
print("0: Reliable")
print("Distribution of labels:")
print(news_d.label.value_counts());
Producción:
1: Unreliable
0: Reliable
Distribution of labels:
1 10413
0 10387
Name: label, dtype: int64
print(round(news_d.label.value_counts(normalize=True),2)*100);
Producción:
1 50.0
0 50.0
Name: label, dtype: float64
La cantidad de artículos no confiables (falsos o 1) es 10413, mientras que la cantidad de artículos confiables (confiables o 0) es 10387. Casi el 50% de los artículos son falsos. Por lo tanto, la métrica de precisión medirá qué tan bien funciona nuestro modelo al construir un clasificador.
En esta sección, limpiaremos nuestro conjunto de datos para hacer algunos análisis:
# Constants that are used to sanitize the datasets
column_n = ['id', 'title', 'author', 'text', 'label']
remove_c = ['id','author']
categorical_features = []
target_col = ['label']
text_f = ['title', 'text']
# Clean Datasets
import nltk
from nltk.corpus import stopwords
import re
from nltk.stem.porter import PorterStemmer
from collections import Counter
ps = PorterStemmer()
wnl = nltk.stem.WordNetLemmatizer()
stop_words = stopwords.words('english')
stopwords_dict = Counter(stop_words)
# Removed unused clumns
def remove_unused_c(df,column_n=remove_c):
df = df.drop(column_n,axis=1)
return df
# Impute null values with None
def null_process(feature_df):
for col in text_f:
feature_df.loc[feature_df[col].isnull(), col] = "None"
return feature_df
def clean_dataset(df):
# remove unused column
df = remove_unused_c(df)
#impute null values
df = null_process(df)
return df
# Cleaning text from unused characters
def clean_text(text):
text = str(text).replace(r'http[\w:/\.]+', ' ') # removing urls
text = str(text).replace(r'[^\.\w\s]', ' ') # remove everything but characters and punctuation
text = str(text).replace('[^a-zA-Z]', ' ')
text = str(text).replace(r'\s\s+', ' ')
text = text.lower().strip()
#text = ' '.join(text)
return text
## Nltk Preprocessing include:
# Stop words, Stemming and Lemmetization
# For our project we use only Stop word removal
def nltk_preprocess(text):
text = clean_text(text)
wordlist = re.sub(r'[^\w\s]', '', text).split()
#text = ' '.join([word for word in wordlist if word not in stopwords_dict])
#text = [ps.stem(word) for word in wordlist if not word in stopwords_dict]
text = ' '.join([wnl.lemmatize(word) for word in wordlist if word not in stopwords_dict])
return text
En el bloque de código de arriba:
re
para expresiones regulares.nltk.corpus
. Cuando trabajamos con palabras, particularmente cuando consideramos la semántica, a veces necesitamos eliminar palabras comunes que no agregan ningún significado significativo a una declaración, como "but"
, "can"
, "we"
, etc.PorterStemmer
se utiliza para realizar palabras derivadas con NLTK. Los lematizadores despojan a las palabras de sus afijos morfológicos, dejando únicamente la raíz de la palabra.WordNetLemmatizer()
de la biblioteca NLTK para la lematización. La lematización es mucho más eficaz que la derivación . Va más allá de la reducción de palabras y evalúa todo el léxico de un idioma para aplicar el análisis morfológico a las palabras, con el objetivo de eliminar los extremos flexivos y devolver la forma base o de diccionario de una palabra, conocida como lema.stopwords.words('english')
permítanos ver la lista de todas las palabras vacías en inglés admitidas por NLTK.remove_unused_c()
La función se utiliza para eliminar las columnas no utilizadas.None
el uso de la null_process()
función.clean_dataset()
, llamamos remove_unused_c()
y null_process()
funciones. Esta función es responsable de la limpieza de datos.clean_text()
función.nltk_preprocess()
función para ese propósito.Preprocesando el text
y title
:
# Perform data cleaning on train and test dataset by calling clean_dataset function
df = clean_dataset(news_d)
# apply preprocessing on text through apply method by calling the function nltk_preprocess
df["text"] = df.text.apply(nltk_preprocess)
# apply preprocessing on title through apply method by calling the function nltk_preprocess
df["title"] = df.title.apply(nltk_preprocess)
# Dataset after cleaning and preprocessing step
df.head()
Producción:
title text label
0 house dem aide didnt even see comeys letter ja... house dem aide didnt even see comeys letter ja... 1
1 flynn hillary clinton big woman campus breitbart ever get feeling life circle roundabout rather... 0
2 truth might get fired truth might get fired october 29 2016 tension ... 1
3 15 civilian killed single u airstrike identified video 15 civilian killed single u airstrike id... 1
4 iranian woman jailed fictional unpublished sto... print iranian woman sentenced six year prison ... 1
En esta sección realizaremos:
Las palabras más frecuentes aparecen en negrita y de mayor tamaño en una nube de palabras. Esta sección creará una nube de palabras para todas las palabras del conjunto de datos.
Se usará la función de la biblioteca de WordCloudwordcloud()
y generate()
se utilizará para generar la imagen de la nube de palabras:
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
# initialize the word cloud
wordcloud = WordCloud( background_color='black', width=800, height=600)
# generate the word cloud by passing the corpus
text_cloud = wordcloud.generate(' '.join(df['text']))
# plotting the word cloud
plt.figure(figsize=(20,30))
plt.imshow(text_cloud)
plt.axis('off')
plt.show()
Producción:
Nube de palabras solo para noticias confiables:
true_n = ' '.join(df[df['label']==0]['text'])
wc = wordcloud.generate(true_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
Producción:
Nube de palabras solo para noticias falsas:
fake_n = ' '.join(df[df['label']==1]['text'])
wc= wordcloud.generate(fake_n)
plt.figure(figsize=(20,30))
plt.imshow(wc)
plt.axis('off')
plt.show()
Producción:
Un N-grama es una secuencia de letras o palabras. Un unigrama de carácter se compone de un solo carácter, mientras que un bigrama comprende una serie de dos caracteres. De manera similar, los N-gramas de palabras se componen de una serie de n palabras. La palabra "unidos" es un 1 gramo (unigrama). La combinación de las palabras "estado unido" es de 2 gramos (bigrama), "ciudad de nueva york" es de 3 gramos.
Grafiquemos el bigrama más común en las noticias confiables:
def plot_top_ngrams(corpus, title, ylabel, xlabel="Number of Occurences", n=2):
"""Utility function to plot top n-grams"""
true_b = (pd.Series(nltk.ngrams(corpus.split(), n)).value_counts())[:20]
true_b.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
plt.show()
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Bigrams', "Bigram", n=2)
El bigrama más común en las noticias falsas:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Bigrams', "Bigram", n=2)
El trigrama más común en noticias confiables:
plot_top_ngrams(true_n, 'Top 20 Frequently Occuring True news Trigrams', "Trigrams", n=3)
Para noticias falsas ahora:
plot_top_ngrams(fake_n, 'Top 20 Frequently Occuring Fake news Trigrams', "Trigrams", n=3)
Los gráficos anteriores nos dan algunas ideas sobre cómo se ven ambas clases. En la siguiente sección, usaremos la biblioteca de transformadores para construir un detector de noticias falsas.
Esta sección tomará código ampliamente del tutorial BERT de ajuste fino para hacer un clasificador de noticias falsas utilizando la biblioteca de transformadores. Entonces, para obtener información más detallada, puede dirigirse al tutorial original .
Si no instaló transformadores, debe:
$ pip install transformers
Importemos las bibliotecas necesarias:
import torch
from transformers.file_utils import is_tf_available, is_torch_available, is_torch_tpu_available
from transformers import BertTokenizerFast, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
import numpy as np
from sklearn.model_selection import train_test_split
import random
Queremos que nuestros resultados sean reproducibles incluso si reiniciamos nuestro entorno:
def set_seed(seed: int):
"""
Helper function for reproducible behavior to set the seed in ``random``, ``numpy``, ``torch`` and/or ``tf`` (if
installed).
Args:
seed (:obj:`int`): The seed to set.
"""
random.seed(seed)
np.random.seed(seed)
if is_torch_available():
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
# ^^ safe to call this function even if cuda is not available
if is_tf_available():
import tensorflow as tf
tf.random.set_seed(seed)
set_seed(1)
El modelo que vamos a utilizar es el bert-base-uncased
:
# the model we gonna train, base uncased BERT
# check text classification models here: https://huggingface.co/models?filter=text-classification
model_name = "bert-base-uncased"
# max sequence length for each document/sentence sample
max_length = 512
Cargando el tokenizador:
# load the tokenizer
tokenizer = BertTokenizerFast.from_pretrained(model_name, do_lower_case=True)
Limpiemos ahora los NaN
valores de las columnas text
, author
y :title
news_df = news_d[news_d['text'].notna()]
news_df = news_df[news_df["author"].notna()]
news_df = news_df[news_df["title"].notna()]
A continuación, crear una función que tome el conjunto de datos como un marco de datos de Pandas y devuelva las divisiones de entrenamiento/validación de textos y etiquetas como listas:
def prepare_data(df, test_size=0.2, include_title=True, include_author=True):
texts = []
labels = []
for i in range(len(df)):
text = df["text"].iloc[i]
label = df["label"].iloc[i]
if include_title:
text = df["title"].iloc[i] + " - " + text
if include_author:
text = df["author"].iloc[i] + " : " + text
if text and label in [0, 1]:
texts.append(text)
labels.append(label)
return train_test_split(texts, labels, test_size=test_size)
train_texts, valid_texts, train_labels, valid_labels = prepare_data(news_df)
La función anterior toma el conjunto de datos en un tipo de marco de datos y los devuelve como listas divididas en conjuntos de entrenamiento y validación. Establecer include_title
en True
significa que agregamos la title
columna a la text
que vamos a usar para el entrenamiento, establecer include_author
en True
significa que también agregamos author
al texto.
Asegurémonos de que las etiquetas y los textos tengan la misma longitud:
print(len(train_texts), len(train_labels))
print(len(valid_texts), len(valid_labels))
Producción:
14628 14628
3657 3657
Usemos el tokenizador BERT para tokenizar nuestro conjunto de datos:
# tokenize the dataset, truncate when passed `max_length`,
# and pad with 0's when less than `max_length`
train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=max_length)
valid_encodings = tokenizer(valid_texts, truncation=True, padding=True, max_length=max_length)
Convertir las codificaciones en un conjunto de datos de PyTorch:
class NewsGroupsDataset(torch.utils.data.Dataset):
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {k: torch.tensor(v[idx]) for k, v in self.encodings.items()}
item["labels"] = torch.tensor([self.labels[idx]])
return item
def __len__(self):
return len(self.labels)
# convert our tokenized data into a torch Dataset
train_dataset = NewsGroupsDataset(train_encodings, train_labels)
valid_dataset = NewsGroupsDataset(valid_encodings, valid_labels)
Usaremos BertForSequenceClassification
para cargar nuestro modelo de transformador BERT:
# load the model
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)
Establecemos num_labels
a 2 ya que es una clasificación binaria. A continuación, la función es una devolución de llamada para calcular la precisión en cada paso de validación:
from sklearn.metrics import accuracy_score
def compute_metrics(pred):
labels = pred.label_ids
preds = pred.predictions.argmax(-1)
# calculate accuracy using sklearn's function
acc = accuracy_score(labels, preds)
return {
'accuracy': acc,
}
Vamos a inicializar los parámetros de entrenamiento:
training_args = TrainingArguments(
output_dir='./results', # output directory
num_train_epochs=1, # total number of training epochs
per_device_train_batch_size=10, # batch size per device during training
per_device_eval_batch_size=20, # batch size for evaluation
warmup_steps=100, # number of warmup steps for learning rate scheduler
logging_dir='./logs', # directory for storing logs
load_best_model_at_end=True, # load the best model when finished training (default metric is loss)
# but you can specify `metric_for_best_model` argument to change to accuracy or other metric
logging_steps=200, # log & save weights each logging_steps
save_steps=200,
evaluation_strategy="steps", # evaluate each `logging_steps`
)
Configuré el valor per_device_train_batch_size
en 10, pero debe configurarlo tan alto como su GPU pueda caber. Establecer el logging_steps
y save_steps
en 200, lo que significa que vamos a realizar una evaluación y guardar los pesos del modelo en cada 200 pasos de entrenamiento.
Puede consultar esta página para obtener información más detallada sobre los parámetros de entrenamiento disponibles.
Instanciamos el entrenador:
trainer = Trainer(
model=model, # the instantiated Transformers model to be trained
args=training_args, # training arguments, defined above
train_dataset=train_dataset, # training dataset
eval_dataset=valid_dataset, # evaluation dataset
compute_metrics=compute_metrics, # the callback that computes metrics of interest
)
Entrenamiento del modelo:
# train the model
trainer.train()
El entrenamiento tarda unas horas en finalizar, dependiendo de su GPU. Si está en la versión gratuita de Colab, debería tomar una hora con NVIDIA Tesla K80. Aquí está la salida:
***** Running training *****
Num examples = 14628
Num Epochs = 1
Instantaneous batch size per device = 10
Total train batch size (w. parallel, distributed & accumulation) = 10
Gradient Accumulation steps = 1
Total optimization steps = 1463
[1463/1463 41:07, Epoch 1/1]
Step Training Loss Validation Loss Accuracy
200 0.250800 0.100533 0.983867
400 0.027600 0.043009 0.993437
600 0.023400 0.017812 0.997539
800 0.014900 0.030269 0.994258
1000 0.022400 0.012961 0.998086
1200 0.009800 0.010561 0.998633
1400 0.007700 0.010300 0.998633
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-200
Configuration saved in ./results/checkpoint-200/config.json
Model weights saved in ./results/checkpoint-200/pytorch_model.bin
<SNIPPED>
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
Saving model checkpoint to ./results/checkpoint-1400
Configuration saved in ./results/checkpoint-1400/config.json
Model weights saved in ./results/checkpoint-1400/pytorch_model.bin
Training completed. Do not forget to share your model on huggingface.co/models =)
Loading best model from ./results/checkpoint-1400 (score: 0.010299865156412125).
TrainOutput(global_step=1463, training_loss=0.04888018785440506, metrics={'train_runtime': 2469.1722, 'train_samples_per_second': 5.924, 'train_steps_per_second': 0.593, 'total_flos': 3848788517806080.0, 'train_loss': 0.04888018785440506, 'epoch': 1.0})
Dado que load_best_model_at_end
está configurado en True
, los mejores pesos se cargarán cuando se complete el entrenamiento. Vamos a evaluarlo con nuestro conjunto de validación:
# evaluate the current model after training
trainer.evaluate()
Producción:
***** Running Evaluation *****
Num examples = 3657
Batch size = 20
[183/183 02:11]
{'epoch': 1.0,
'eval_accuracy': 0.998632759092152,
'eval_loss': 0.010299865156412125,
'eval_runtime': 132.0374,
'eval_samples_per_second': 27.697,
'eval_steps_per_second': 1.386}
Guardando el modelo y el tokenizador:
# saving the fine tuned model & tokenizer
model_path = "fake-news-bert-base-uncased"
model.save_pretrained(model_path)
tokenizer.save_pretrained(model_path)
Aparecerá una nueva carpeta que contiene la configuración del modelo y los pesos después de ejecutar la celda anterior. Si desea realizar una predicción, simplemente use el from_pretrained()
método que usamos cuando cargamos el modelo, y ya está listo.
A continuación, hagamos una función que acepte el texto del artículo como argumento y devuelva si es falso o no:
def get_prediction(text, convert_to_label=False):
# prepare our text into tokenized sequence
inputs = tokenizer(text, padding=True, truncation=True, max_length=max_length, return_tensors="pt").to("cuda")
# perform inference to our model
outputs = model(**inputs)
# get output probabilities by doing softmax
probs = outputs[0].softmax(1)
# executing argmax function to get the candidate label
d = {
0: "reliable",
1: "fake"
}
if convert_to_label:
return d[int(probs.argmax())]
else:
return int(probs.argmax())
Tomé un ejemplo de test.csv
que el modelo nunca vio para realizar inferencias, lo verifiqué y es un artículo real de The New York Times:
real_news = """
Tim Tebow Will Attempt Another Comeback, This Time in Baseball - The New York Times",Daniel Victor,"If at first you don’t succeed, try a different sport. Tim Tebow, who was a Heisman quarterback at the University of Florida but was unable to hold an N. F. L. job, is pursuing a career in Major League Baseball. <SNIPPED>
"""
El texto original está en el entorno de Colab si desea copiarlo, ya que es un artículo completo. Vamos a pasarlo al modelo y ver los resultados:
get_prediction(real_news, convert_to_label=True)
Producción:
reliable
En esta sección, predeciremos todos los artículos en el test.csv
para crear un archivo de envío para ver nuestra precisión en la prueba establecida en la competencia Kaggle :
# read the test set
test_df = pd.read_csv("test.csv")
# make a copy of the testing set
new_df = test_df.copy()
# add a new column that contains the author, title and article content
new_df["new_text"] = new_df["author"].astype(str) + " : " + new_df["title"].astype(str) + " - " + new_df["text"].astype(str)
# get the prediction of all the test set
new_df["label"] = new_df["new_text"].apply(get_prediction)
# make the submission file
final_df = new_df[["id", "label"]]
final_df.to_csv("submit_final.csv", index=False)
Después de concatenar el autor, el título y el texto del artículo, pasamos la get_prediction()
función a la nueva columna para llenar la label
columna, luego usamos to_csv()
el método para crear el archivo de envío para Kaggle. Aquí está mi puntaje de presentación:
Obtuvimos una precisión del 99,78 % y del 100 % en las tablas de clasificación privadas y públicas. ¡Eso es genial!
Muy bien, hemos terminado con el tutorial. Puede consultar esta página para ver varios parámetros de entrenamiento que puede modificar.
Si tiene un conjunto de datos de noticias falsas personalizado para ajustarlo, simplemente tiene que pasar una lista de muestras al tokenizador como lo hicimos nosotros, no cambiará ningún otro código después de eso.
Consulta el código completo aquí , o el entorno de Colab aquí .