Die Zwiebel oder nicht die Zwiebel?


11

The Onion (Warnung: Viele Artikel sind NSFW) ist eine satirische Nachrichtenorganisation, die traditionelle Nachrichtenmedien parodiert. 2014 startete The Onion ClickHole (Warnung: auch häufig NSFW), eine satirische Nachrichten-Website, die "Clickbait" -Seiten wie BuzzFeed parodiert. Dank Poes Gesetz lesen die Leute häufig die Schlagzeilen von Artikeln aus The Onion oder ClickHole und glauben, dass sie wahr sind, ohne zu wissen, dass sie als Satire gedacht sind. Das Gegenteil passiert auch mit lächerlich klingenden echten Nachrichten - die Leute denken oft, dass sie Satire sind, wenn sie es nicht sind.

Diese Verwirrung eignet sich natürlich für ein Spiel - versuchen Sie angesichts einer Schlagzeile zu erraten, ob es sich um eine Satire handelt oder nicht. Bei dieser Herausforderung geht es darum, genau das mit einem Programm zu tun.

Bei einer Nachrichtenüberschrift (eine Zeichenfolge, die nur aus druckbaren ASCII-Zeichen und Leerzeichen besteht) wird ausgegeben, 1ob die Überschrift eine Satire ist oder 0nicht. Ihre Punktzahl ist die Anzahl der korrekten Ausgaben geteilt durch die Gesamtzahl der Überschriften.

Wie üblich, Standard Lücken (vor allem der Optimierung für die Testfälle ) ist nicht erlaubt. Um dies durchzusetzen, werde ich Ihre Programme auf einem Satz von 200 versteckten Testfällen ausführen (100 von The Onion, 100 von Not The Onion). Ihre Lösung darf nicht mehr als 20 Prozentpunkte unter Ihrer Punktzahl in den öffentlichen Testfällen liegen, um gültig zu sein.

Testfälle

Um Testfälle für diese Herausforderung zu erstellen , habe ich 25 Überschriften aus dem Subreddit The Onion (wo Artikel von The Onion und seinen untergeordneten Websites wie ClickHole veröffentlicht werden) und 25 Überschriften aus dem Subreddit Not The Onion (wo echte Nachrichtenartikel ausgewählt wurden) ausgewählt das klingt wie Satire sind gepostet). Die einzigen Änderungen, die ich an den Überschriften vorgenommen habe, waren das Ersetzen "ausgefallener" Anführungszeichen durch reguläre ASCII-Anführungszeichen und die Standardisierung der Großschreibung - alles andere bleibt gegenüber der Überschrift des Originalartikels unverändert. Jede Überschrift steht in einer eigenen Zeile.

Die Zwiebel Schlagzeilen

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

Nicht die Zwiebel Schlagzeilen

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

6
Your score will be the number of correct outputs divided by the total number of headlinesIst Bytecount ein Tie Breaker?
Skidsdev

9
Ich bin etwas durcheinander. Was Art von Lösung erwarten Sie? Jede Lösung muss etwas "für die Testfälle optimieren", abgesehen davon, dass sie eine KI schreibt, die Englisch versteht und Sinn für Humor hat. Zum Beispiel erkennt Arnauld's Lösung, /ly\b/was nur funktioniert, weil die 25 Zwiebel-Schlagzeilen, die Sie ausgewählt haben, mehr Adverbien enthalten, aber soweit ich weiß, können Sie sie leicht mit einer anderen Testbatterie auslösen. Und wer soll sagen, dass seine Koeffizienten nicht ausgewählt wurden, um seine Punktzahl zu optimieren? (Warum sollte er sie nicht optimieren?)
Lynn

10
Diese Testbatterie scheint etwas ungewöhnlich. Es ist, als würde man nach einem Klassifikator fragen, der Hunde auf einem Foto erkennen kann, aber Ihre positiven Testfälle als Fotos von Hunden und Ihre negativen Testfälle aus einem Buzzfeed-Artikel mit dem Titel "25 Fotos von Objekten, von denen Sie schwören, dass sie Hunde sind, aber nein, dreht sich" nimmt Raus sind sie nicht! (# 11 wird dich umhauen!) "Es macht ein Problem schwer genug.
Sophia Lechner

4
Die Herausforderung ist nicht nur schwierig, es ist auch (für mich) nicht klar, was der Unterschied ist. Wenn ich es nicht lösen kann, kann mein Programm es natürlich nicht lösen (das heißt, während ich davon überzeugt
bin

4
Nun, ich habe +36 Stunden damit verbracht, ein künstliches neuronales Netzwerk mit brain.jsund LSTM zu trainieren , mit Beispielen in dieser Ausgabe und 100 anderen Beispielen jedes Typs von bereitgestellten Links, aber das Ergebnis war nicht gut genug mit neuen Titeln, die nicht in Trainingssätzen vorhanden waren . Ich bin fertig: P
Night2

Antworten:


7

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

63,5% (127/200) bei versteckten Testfällen

Eine einfache Heuristik, die auf der Länge des Titels, der Anzahl der Leerzeichen und der Verwendung des -lySuffix basiert .

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

Probieren Sie es online aus!


Dies ist absurd effektiv, wie einfach es ist.
Don Thousand

Diese Lösung erzielte in den versteckten Testfällen 63,5%, ist also gültig.
Mego

Nicht so einfach wie es am Anfang der Sandbox möglich war (100% unter Verwendung von Kapitalisierungsunterschieden, bevor sie standardisiert wurde), aber das ist wirklich einfach.
Zacharý

@Mego Verbessert diese NSFW-Version aus Neugier die Punktzahl für die versteckten Testfälle? :)
Arnauld

@Arnauld 66% mit dieser Version
Mego

6

Python 3, 84%

Ungetestet für versteckte Testfälle.

Dies verwendet Keras LSTM RNN, das in verschiedenen Überschriften trainiert wurde. Um es auszuführen, benötigen Sie Keras Folgendes und das Modell, das ich auf GitHub zur Verfügung gestellt habe: Repo-Link . Sie benötigen das Modell .h5und die Wort- / Vektorzuordnungen sind in .pkl. Das Neueste

Die Abhängigkeiten sind:

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

Die Einstellungen sind:

max_headline_length = 70
word_count = 20740

Das Modell ist:

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'))

Laden Sie nun das Modell und die Worteinbettungen:

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

Und der Code zum Testen, ob eine Zeichenfolge aus 'NotTheOnion' oder 'TheOnion' stammt Ich habe eine schnelle Hilfsfunktion geschrieben, die die Zeichenfolge in die entsprechenden Worteinbettungen konvertiert:

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

Erläuterung

Dieser Code führt ein Modell aus, das die Beziehungen zwischen Wörtern analysiert, indem die Wörter als "Vektor" dargestellt werden. Weitere Informationen zum Einbetten von Wörtern finden Sie hier .

Dies wird auf Schlagzeilen trainiert, aber die Testfälle sind ausgeschlossen .

Dieser Prozess wird nach einigem Verarbeiten automatisiert. Ich habe die endgültige Liste der verarbeiteten Wörter als verteilt, .pklaber beim Einbetten von Wörtern analysieren wir zuerst den Satz und isolieren die Wörter.

Nachdem wir nun die Wörter haben, besteht der nächste Schritt darin, die Unterschiede und Ähnlichkeiten zwischen bestimmten Wörtern zu verstehen, z . B. kingund queenversus dukeund duchess. Diese Einbettungen finden nicht zwischen den tatsächlichen Wörtern statt, sondern zwischen Zahlen, die die Wörter darstellen, die in der .pklDatei gespeichert sind . Wörter, die die Maschine nicht versteht, werden einem speziellen Wort zugeordnet <UNK>, wodurch wir verstehen können, dass es dort ein Wort gibt, aber nicht genau bekannt ist, was die Bedeutung ist.

Nachdem die Wörter verstanden werden können, muss die Wortfolge (Überschrift) analysiert werden können. Dies ist, was 'LSTM' tut, ein LTSM ist eine Art 'RNN'-Zelle, die den verschwindenden Gradienteneffekt vermeidet. Einfacher gesagt, es nimmt eine Folge von Wörtern auf und ermöglicht es uns, Beziehungen zwischen ihnen zu finden.

Jetzt ist die letzte Ebene, Densewas im Grunde bedeutet, dass sie wie ein Array ist, was bedeutet, dass die Ausgabe wie folgt lautet : [probability_is_not_onion, probability_is_onion]. Indem wir herausfinden, welches größer ist, können wir auswählen, welches das sicherste Ergebnis für die gegebene Überschrift ist.


3

Python 3 + Keras, 41/50 = 82%

83% (166/200) bei versteckten Testfällen

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.h5und vocabulary.jsonkann von hier (sehr groß) und hier abgerufen werden .

Vollständig verbundener Klassifikator, verbunden mit einem vorab trainierten Stimmungsanalysemodell DeepMoji, das aus gestapelten bidirektionalen LSTMs und einem Aufmerksamkeitsmechanismus besteht. Ich habe die DeepMoji-Ebenen eingefroren und die letzte Softmax-Ebene herausgenommen, nur die vollständig verbundenen Ebenen trainiert, dann die DeepMoji-Ebenen aufgefroren und sie gemeinsam für die Feinabstimmung trainiert. Der Aufmerksamkeitsmechanismus stammt von https://github.com/bfelbo/DeepMoji/blob/master/deepmoji/attlayer.py (ich wollte nicht den gesamten Code als Abhängigkeit für eine Klasse verwenden müssen, zumal dies der Fall ist Python 2 und eher unhandlich als Modul zu verwenden ...)

Dies ist bei Megos Testsatz überraschend schlecht, wenn man bedenkt, dass bei meinem eigenen größeren Validierungssatz> 90% erreicht werden. Damit bin ich noch nicht fertig.


83% auf versteckte Testfälle, vorausgesetzt ich habe es richtig ausgeführt
Mego

1

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

96% (192/200) bei versteckten Testfällen

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));
};

Dies erfordert zwei große JSON-Dateien, die ich hier oder auf "TiO" nicht ablegen kann. Bitte laden Sie sie von den folgenden Links und sie mit den Speichern words.jsonund bags.jsonNamen, in dem gleichen Ordner wie JS - Datei. Es gibt auch einen Link für eine JS-Datei mit Testfällen und Ergebnis / Prozent Druck. Sie können Ihre versteckten Testfälle in onionsund nonOnionsVariablen einfügen.

Führen Sie nach dem Speichern aller 3 Dateien im selben Verzeichnis aus node onion.js.

Die OFunktion wird zurückgegeben, truewenn es sich um eine Zwiebel handelt und falsewenn dies nicht der Fall ist. Verwendet eine große Liste von Wortbeuteln (ohne Reihenfolge), um festzustellen, ob die Eingabezeichenfolge Zwiebel ist. Art hartcodiert, funktioniert aber sehr gut bei einer Vielzahl von zufälligen Testfällen.


Diese Lösung erhält 96% auf die versteckten Testfälle
Mego

0

Arnauld's Lösung abarbeiten

JavaScript (ES6), 41/50

64% (128/200) bei versteckten Testfällen

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) bei versteckten Testfällen (ungültig)

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

Das Konzept Länge + Wortanzahl + "Ly" funktioniert ziemlich gut. Ich konnte ein paar weitere Punkte herausgreifen, indem ich nach dem Wort "Dad" suchte (wann sprechen echte Artikel über die Väter der Leute in der dritten Person im Titel?) Und Ein zusätzlicher Punkt durch Ändern der "ly" -Suchheuristik und Überprüfen des Vorhandenseins von Zahlen im Titel (was im allgemeinen Fall außerhalb des Tests möglicherweise weniger gültig ist, sodass ich beide Lösungen belassen habe).


Ich weiß nicht über den Vater Teil ... scheint mir ein bisschen wie die Optimierung des Testfalls ...
Don Thousand

Und ja, ich kann viele Not the Onion-Artikel finden, in denen Väter erwähnt werden
Don Thousand

Es gibt wahrscheinlich einen besseren Weg, dies als Teil der Heuristik zu tun und nicht nur einen harten "Gewinn", wenn es Papa enthält, aber ich stelle mir vor, dass es auch außerhalb der Testdatenbank bei The Onion
TiKevin83

Ihre erste Lösung erzielte in den versteckten Testfällen 64%, ist also gültig. Ihre zweite Lösung erzielte in den versteckten Testfällen 62,5%, ist also nicht gültig.
Mego

@ Mego Was für ein enger Spielraum ...
user202729
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.