Loignon ou pas loignon?

The Onion (avertissement: de nombreux articles sont NSFW) est une organisation de presse satirique qui parodie les médias dinformation traditionnels. En 2014, The Onion a lancé ClickHole (avertissement: également fréquemment NSFW), un site Web dactualités satiriques qui parodie des sites « clickbait » comme BuzzFeed. Grâce à la Loi de Poe , il est assez courant pour les gens de lire les titres des articles de The Onion ou ClickHole et de les croire vrais, sans le savoir quils sont destinés à être satiriques. Linverse se produit également avec de vraies nouvelles qui semblent ridicules – les gens pensent souvent quils sont de la satire alors quils ne le sont pas.

Cette confusion se prête naturellement à un jeu – étant donné un titre dactualité, essayez de deviner si ou ce nest pas de la satire. Ce défi consiste à faire exactement cela avec un programme.

Étant donné un titre dactualité (une chaîne composée uniquement de caractères ASCII imprimables et despaces), affichez 1 si le headline est satire, ou 0 si ce nest pas le cas. Votre score sera le nombre de sorties correctes divisé par le nombre total de titres.

Comme dhabitude, échappatoires standards (en particulier loptimisation pour les cas de test ) ne sont pas autorisées. Pour appliquer cela, je vais exécuter vos programmes sur un ensemble de 200 cas de test cachés (100 de The Onion, 100 de Not The Onion). Votre solution ne doit pas obtenir plus de 20 points de pourcentage de moins que votre score dans les cas de test publics pour être valide.

Cas de test

Pour proposer des cas de test pour ce défi , Jai choisi 25 titres de The Onion subreddit (où des articles de The Onion et de ses sites enfants, comme ClickHole, sont publiés) et 25 titres de le subreddit Not The Onion (où de vrais articles de nouvelles qui ressemblent à de la satire sont publiés). Les seules modifications que jai apportées aux titres ont été le remplacement des guillemets « fantaisie » par des guillemets ASCII normaux et la normalisation des majuscules – tout le reste reste inchangé par rapport au titre de larticle dorigine. Chaque titre est sur sa propre ligne.

Les titres de loignon

Trump Warns Removing Confederate Statues Could Be Slippery Slope To Eliminating Racism Entirely "No Way To Prevent This," Says Only Nation Where This Regularly Happens My Doctor Told Me I Should Vaccinate My Children, But Then Someone Much Louder Than My Doctor Told Me I Shouldn"t Man At Park Who Set Up Table Full Of Water Cups Has No Idea How Passing Marathon Runners Got Impression They Can Take Them This Child Would Have Turned 6 Today If His Mother Hadn"t Given Birth To Him In October Incredible Realism: The Campaign In The Next "Call Of Duty" Will Begin At Your Avatar"s High School Cafeteria When He"s Being Tricked Into Joining The Military By A Recruiter "Sometimes Things Have To Get Worse Before They Get Better," Says Man Who Accidentally Turned Shower Knob Wrong Way Report: Uttering Phrase "Easy Does It" Prevents 78% Of Drywall Damage While Moving Furniture Barbara Bush Passes Away Surrounded By Loved Ones, Jeb Family Has Way Too Many Daughters For Them Not To Have Been Trying For Son News: Privacy Win! Facebook Is Adding A "Protect My Data" Button That Does Nothing But Feels Good To Press Dalai Lama Announces Next Life To Be His Last Before Retirement Researchers Find Decline In Facebook Use Could Be Directly Linked To Desire To Be Happy, Fully Functioning Person Manager Of Combination Taco Bell/KFC Secretly Considers It Mostly A Taco Bell Trump: "It"s My Honor To Deliver The First-Ever State Of The Union" Daring To Dream: Jeff Bezos Is Standing Outside A Guitar Center Gazing Longingly At A $200 Billion Guitar Area Dad Looking To Get Average Phone Call With Adult Son Down To 47.5 Seconds Experts Warn Beef Could Act As Gateway Meat To Human Flesh Jeff Bezos Named Amazon Employee Of The Month Dad Suggests Arriving At Airport 14 Hours Early Report: Only 3% Of Conversations Actually Need To Happen Delta Pilot Refuses To Land Until Gun Control Legislation Passed Family Wishes Dad Could Find Healthier Way To Express Emotions Than Bursting Into Full-Blown Musical Number New Honda Commercial Openly Says Your Kids Will Die In A Car Crash If You Buy A Different Brand Teacher Frustrated No One In Beginner Yoga Class Can Focus Chakras Into Energy Blast 

Titres Not The Onion

Man Rescued From Taliban Didn"t Believe Donald Trump Was President Nat Geo Hires Jeff Goldblum To Walk Around, Being Professionally Fascinated By Things Mike Pence Once Ratted Out His Fraternity Brothers For Having A Keg Reddit CEO Tells User, "We Are Not The Thought Police," Then Suspends That User Trump Dedicates Golf Trophy To Hurricane Victims Uber"s Search For A Female CEO Has Been Narrowed Down To 3 Men ICE Director: ICE Can"t Be Compared To Nazis Since We"re Just Following Orders Passenger Turned Away From Two Flights After Wearing 10 Layers Of Clothing To Avoid Luggage Fee Somali Militant Group Al-Shabaab Announces Ban On Single-Use Plastic Bags UPS Loses Family"s $846k Inheritance, Offers To Refund $32 Shipping Fee Teen Suspended From High School After Her Anti-Bullying Video Hurts Principal"s Feelings Alabama Lawmaker: We Shouldn"t Arm Teachers Because Most Are Women Cat Named After Notorious B.I.G. Shot Multiple Times - And Survives EPA Head Says He Needs To Fly First Class Because People Are Mean To Him In Coach Apology After Japanese Train Departs 20 Seconds Early Justin Bieber Banned From China In Order To "Purify" Nation Alcohol Level In Air At Fraternity Party Registers On Breathalyzer NPR Tweets The Declaration Of Independence, And People Freak Out About A "Revolution" Man Who Mowed Lawn With Tornado Behind Him Says He "Was Keeping An Eye On It." After Eating Chipotle For 500 Days, An Ohio Man Says He"s Ready For Something New "El Chapo" Promises Not To Kill Any Jurors From Upcoming Federal Trial After 4th DWI, Man Argues Legal Limit Discriminates Against Alcoholics Palestinian Judge Bans Divorce During Ramadan Because "People Make Hasty Decisions When They"re Hungry" Argentinian Officers Fired After Claiming Mice Ate Half A Ton Of Missing Marijuana "Nobody Kill Anybody": Murder-Free Weekend Urged In Baltimore 

Commentaires

  • Your score will be the number of correct outputs divided by the total number of headlines Est-ce que bytecount est un bris dégalité?
  • Je ‘ un petit peu confus. Quel type de solution attendez-vous? Chaque solution devra  » optimiser pour les cas de test  » quelque peu, barre lécriture dune IA qui comprend langlais et a le sens de lhumour. Par exemple, la solution dArnauld ‘ détecte /ly\b/ qui fonctionne uniquement parce que le 25 Onio n les titres que vous avez choisis contiennent plus dadverbes, mais pour autant que je sache, vous pouvez facilement le déclencher avec une batterie de test différente. Et qui ‘ pour dire que ses coefficients ne sont pas ‘ choisis pour optimiser son score? (Pourquoi les ‘ ne les optimiseraient-ils pas?)
  • Cette batterie de test semble un peu inhabituelle. Cest ‘ comme demander un classificateur capable de détecter les chiens sur une photo, mais prendre vos cas de test positifs comme des photos de chiens et vos cas de test négatifs à partir dun article Buzzfeed intitulé  » 25 photos dobjets que vous ‘ Je jure sont des chiens, mais non, il savère quils ne sont pas ‘ t! (# 11 Will Blow Your Mind!)  » Cela rend un problème assez difficile plus difficile.
  • Non seulement le défi est difficile, mais il ‘ est également non évident (pour moi) ce que ‘ est la différence. Si je peux ‘ t le résoudre, bien sûr mon programme ne pourra ‘ t le résoudre (cest-à-dire, tout en me convaincant quil ne ‘ t hardcode pour les cas de test)
  • Eh bien, jai passé +36 heures à entraîner un réseau de neurones artificiels en utilisant brain.js et LSTM, avec des exemples dans ce numéro et 100 autres échantillons de chaque type à partir des liens fournis, mais le résultat nétait ‘ pas assez bon avec de nouveaux titres qui nétaient ‘ t présent dans les ensembles de formation. Jai ‘ jai terminé: P

Réponse

JavaScript ( ES7), 39/50 (78%)

63,5% (127/200) sur les cas de test cachés

Une heuristique simple basée sur la longueur du titre, le nombre despaces et utilisation du suffixe -ly.

 isOnion = str => str.length ** 0.25 + str.split(" ").length ** 1.25 * 2 + str.split(/ly\b/).length ** 1.75 * 7 > 76  

Essayez-le en ligne!

Commentaires

  • Cest absurdement efficace pour sa simplicité.
  • Cette solution a obtenu un score de 63,5% sur les cas de test cachés, donc cest valide.
  • Pas aussi simple que possible au début du bac à sable (100%, en utilisant les différences de capitalisation avant quil ne soit standardisé) mais cest vraiment simple.
  • @Mego Par curiosité, cette version NSFW améliore-t-elle le score sur les cas de test cachés? 🙂
  • @Arnauld 66% avec cette version

Réponse

Python 3, 84%

Non testé sur les cas de test cachés.

Ceci utilise Keras LSTM RNN entraîné sur divers titres. Pour lexécuter, vous avez besoin des éléments suivants de Keras et du modèle que jai mis à disposition sur GitHub: lien de dépôt . Vous aurez besoin du modèle .h5 et les mappages mot / vecteur sont dans .pkl. Les dernières

Les dépendances sont:

import numpy as np from pickle import load from keras.preprocessing import sequence, text from keras.models import Sequential from keras.layers import Dense, Embedding, SpatialDropout1D, LSTM, Dropout from keras.regularizers import l2 import re 

Les paramètres sont:

max_headline_length = 70 word_count = 20740 

Le modèle est:

model = Sequential() model.add(Embedding(word_count, 32, input_length=max_headline_length)) model.add(SpatialDropout1D(0.4)) model.add(LSTM(64, kernel_regularizer=l2(0.005), dropout=0.3, recurrent_dropout=0.3)) model.add(Dropout(0.5)) model.add(Dense(32, kernel_regularizer=l2(0.005))) model.add(Dropout(0.5)) model.add(Dense(2, kernel_regularizer=l2(0.001), activation="softmax")) 

Maintenant pour charger le modèle et le mot embeddings:

model.load_weights("model.h5") word_to_index = load(open("words.pkl", "rb")) 

Et le code pour tester si une chaîne provient de « NotTheOnion » ou « TheOnion « Jai » écrit une fonction daide rapide qui convertit la chaîne en mots incorporés respectifs:

def get_words(string): words = [] for word in re.finditer("[a-z]+|[\"".;/!?]", string.lower()): words.append(word.group(0)) return words def words_to_indexes(words): return [word_to_index.get(word, 0) for word in words] def format_input(word_indexes): return sequence.pad_sequences([word_indexes], maxlen=max_headline_length)[0] def get_type(string): words = words_to_indexes(get_words(string)) result = model.predict(np.array([format_input(words)]))[0] if result[0] > result[1]: site = "NotTheOnion" else: site = "TheOnion" return site 

Explication

Ce code exécute un modèle qui analyse les relations entre les mots en représentant les mots comme un «vecteur». Vous pouvez en savoir plus sur lintégration de mots ici .

Ceci est formé sur les titres mais les cas de test sont exclus .

Ce processus est automatisé après un certain temps de traitement. Jai distribué la liste finale de mots traités sous forme de .pkl mais ce qui se passe dans lincorporation de mots, cest dabord danalyser la phrase et disoler les mots.

Après nous maintenant avoir les mots, la prochaine étape est de pouvoir comprendre les différences et les similitudes entre certains mots, par exemple king et queen versus duke et duchess. Ces imbrications ne se produisent pas entre les mots réels mais entre les nombres représentant les mots qui sont ce qui est stocké dans le . Les mots que la machine ne comprend pas sont mappés sur un mot spécial <UNK> qui nous permet de comprendre quil y a un mot là-bas mais que lon ne sait pas exactement quel est le sens.

Maintenant que les mots sont compréhensibles, la séquence des mots (titre) doit pouvoir être analysée. Cest ce que fait « LSTM », un LTSM est un type de cellule « RNN » qui évite leffet de dégradé de disparition. Plus simplement, il prend une séquence de mots et il nous permet de trouver des relations entre eux.

Le dernier calque est maintenant Dense ce qui signifie essentiellement que cest un peu comme un tableau, ce qui signifie que la sortie est comme: [probability_is_not_onion, probability_is_onion]. En trouvant celui qui est le plus grand, nous pouvons choisir celui qui est le résultat le plus sûr pour le titre donné.

Réponse

Python 3 + Keras, 41/50 = 82%

83% (166/200) sur les cas de test masqués

import json import keras import numpy import re from keras import backend as K STRIP_PUNCTUATION = re.compile(r"[^a-z0-9 ]+") class AttentionWeightedAverage(keras.engine.Layer): def __init__(self, return_attention=False, **kwargs): self.init = keras.initializers.get("uniform") self.supports_masking = True self.return_attention = return_attention super(AttentionWeightedAverage, self).__init__(**kwargs) def build(self, input_shape): self.input_spec = [keras.engine.InputSpec(ndim=3)] assert len(input_shape) == 3 self.W = self.add_weight(shape=(input_shape[2], 1), name="{}_W".format(self.name), initializer=self.init) self.trainable_weights = [self.W] super(AttentionWeightedAverage, self).build(input_shape) def call(self, x, mask=None): logits = K.dot(x, self.W) x_shape = K.shape(x) logits = K.reshape(logits, (x_shape[0], x_shape[1])) ai = K.exp(logits - K.max(logits, axis=-1, keepdims=True)) if mask is not None: mask = K.cast(mask, K.floatx()) ai = ai * mask att_weights = ai / (K.sum(ai, axis=1, keepdims=True) + K.epsilon()) weighted_input = x * K.expand_dims(att_weights) result = K.sum(weighted_input, axis=1) if self.return_attention: return [result, att_weights] return result def get_output_shape_for(self, input_shape): return self.compute_output_shape(input_shape) def compute_output_shape(self, input_shape): output_len = input_shape[2] if self.return_attention: return [(input_shape[0], output_len), (input_shape[0], input_shape[1])] return (input_shape[0], output_len) def compute_mask(self, input, input_mask=None): if isinstance(input_mask, list): return [None] * len(input_mask) else: return None if __name__ == "__main__": model = keras.models.load_model("combined.h5", custom_objects={"AttentionWeightedAverage": AttentionWeightedAverage}) with open("vocabulary.json", "r") as fh: vocab = json.load(fh) while True: try: headline = input() except EOFError: break tokens = STRIP_PUNCTUATION.sub("", headline.lower()).split() inp = numpy.zeros((1, 45)) for i, token in enumerate(tokens): try: inp[0,i] = vocab[token] except KeyError: inp[0,i] = 1 print(model.predict(inp)[0][0] > 0.3) 

combined.h5 et vocabulary.json peuvent être extraits de ici (très grand) et ici .

Classificateur entièrement connecté connecté à un modèle danalyse des sentiments pré-entraîné DeepMoji, qui se compose de LSTM bidirectionnels empilés et dun mécanisme dattention. Jai gelé les couches DeepMoji et sorti la couche softmax finale, formé uniquement les couches entièrement connectées, puis dégelées les couches DeepMoji et les ai entraînées ensemble pour un réglage fin. Le mécanisme attentionnel est tiré de https://github.com/bfelbo/DeepMoji/blob/master/deepmoji/attlayer.py (je ne voulais pas avoir à utiliser tout leur code comme une dépendance pour une classe, dautant plus que cest Python 2 et plutôt difficile à utiliser comme module …)

Cela fonctionne étonnamment mal sur lensemble de test de Mego, étant donné que sur ma propre validation plus large, il obtient> 90%. Donc je « nai pas encore fini avec ça.

Commentaires

  • 83% sur les cas de test cachés, en supposant que je lai exécuté correctement

Réponse

JavaScript ( Node.js ), 98% (49/50)

96% (192/200) sur les cas de test masqués

 const words = require("./words"); const bags = require("./bags"); let W = s => s.replace(/[^A-Za-z0-9 ]/g, "").toLowerCase().split(" ").filter(w => w.length > 3); let M = b => { for (let i = 0; i < bags.length; i++) { let f = true; for (let j = 0; j < bags[i].length; j++) if (!b.includes(bags[i][j])) { f = false; break; } if (f) return true; } return false; }; let O = s => { let b = []; W(s).forEach(w => { let p = words.indexOf(w); if (p >= 0) b.push(p); }); return (b.length > 0 && M(b)); };  

Cela nécessite deux gros fichiers JSON que je ne peux « t les placer ici ou sur  » TiO « . Veuillez les télécharger à partir des liens suivants et les enregistrer avec words.json et noms, dans le même dossier que le fichier JS. Il existe également un lien pour un fichier JS avec des cas de test et des résultats / pourcentage dimpression.Vous pouvez placer vos cas de test masqués dans des variables onions et nonOnions.

Après avoir enregistré les 3 fichiers dans le même répertoire, exécutez node onion.js.

La fonction O renverra true sil sagit doignon et false si ce nest pas « t. Utilise une grande liste de sacs de mots (sans ordre) pour détecter si la chaîne dentrée est de loignon. Genre de codage en dur, mais fonctionne très bien sur une variété de tests aléatoires cas.

Commentaires

  • Cette solution obtient 96% sur les cas de test masqués

Réponse

Travailler avec la solution dArnauld

JavaScript (ES6), 41/50

64% (128/200) sur caché cas de test

str.includes("Dad") || str.length ** .25 + str.split(" ").length ** 1.25 * 2 + str.split(/ly\b/).length ** 1.75 * 7 > 76 

JavaScript (ES6), 42/50

62,5% (125/200) sur les cas de test masqués (invalide)

isOnion = str => str.includes("Dad") || str.length ** .25 + str.split(" ").length ** 1.25 * 2 + str.split(" ").filter(w => w.length > 3 && w.split(/ly/).length > 1).length * 23.54 + /\d/.test(str) * 8 > 76 

La longueur + le nombre de mots + « ly « le concept fonctionne plutôt bien, jai pu saisir quelques points supplémentaires en vérifiant le mot » papa « (quand les vrais articles parlent-ils des papas des gens à la troisième personne dans le titre?) et un point supplémentaire en changeant lheuristique de recherche « ly » et vérification de la présence de nombres dans le titre (ce qui peut être moins valable dans le cas général en dehors du test, jai donc laissé les deux solutions)

Commentaires

  • Je ne sais ‘ pas pour la partie papa … cela me semble un peu comme optimiser le cas de test …
  • Et oui, je peux trouver de nombreux articles sur Not the Onion mentionnant les papas
  • Il y a ‘ probablement une meilleure façon de le faire dans le cadre de lheuristique et pas seulement un dur  » win  » sil contient papa, mais jimagine même en dehors de la base de données de test parler abstraitement dun  » Papa  » est plus courant sur The Onion
  • Votre première solution a obtenu un score de 64% sur les cas de test cachés, elle est donc valide. Votre deuxième solution a obtenu un score de 62,5% sur les cas de test masqués, elle nest donc pas valide.
  • @Mego Quelle marge proche …

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *