The Onion (waarschuwing: veel artikelen zijn NSFW) is een satirische nieuwsorganisatie die parodieert traditionele nieuwsmedia. In 2014 lanceerde The Onion ClickHole (waarschuwing: ook vaak NSFW), een satirische nieuwswebsite die “clickbait” -sites zoals BuzzFeed parodieert. Dankzij Wet van Poe komt het vrij vaak voor dat mensen de koppen van artikelen uit The Onion of ClickHole lezen en geloven dat ze waar zijn, zonder het te weten dat ze bedoeld zijn als satire. Het omgekeerde gebeurt ook met belachelijk klinkende echte nieuwsverhalen – mensen denken vaak dat ze satire zijn terwijl ze dat niet zijn.
Deze verwarring leent zich natuurlijk voor een spel – probeer met een nieuwskop te raden of niet het is satire. Bij deze uitdaging gaat het erom precies dat te doen met een programma.
Gegeven een nieuwskop (een string die alleen uit afdrukbare ASCII-tekens en spaties bestaat), voer dan 1
uit als de kop is satire, of 0
als dat niet het geval is. Uw score is het aantal correcte uitvoer gedeeld door het totale aantal koppen.
Zoals gewoonlijk, standaard mazen (vooral optimaliseren voor de testgevallen ) zijn niet toegestaan. Om dit af te dwingen, laat ik je programmas draaien op een set van 200 verborgen testcases (100 van The Onion, 100 van Not The Onion). Uw oplossing mag niet meer dan 20 procentpunten minder scoren dan uw score op de openbare testcases om geldig te zijn.
Testcases
Om testcases te bedenken voor deze uitdaging , Heb ik 25 koppen gekozen van The Onion subreddit (waar artikelen van The Onion en zijn onderliggende sites, zoals ClickHole, worden gepost) en 25 koppen van de Not The Onion-subreddit (waar echte nieuwsartikelen worden gepost die klinken als satire). De enige wijzigingen die ik in de koppen heb aangebracht, waren het vervangen van mooie aanhalingstekens door gewone ASCII-aanhalingstekens en het standaardiseren van hoofdletters – al het andere blijft ongewijzigd ten opzichte van de kop van het oorspronkelijke artikel. Elke kop staat op een eigen regel.
The Onion headlines
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
Not The Onion headlines
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
Reacties
Antwoord
JavaScript ( ES7), 39/50 (78%)
63,5% (127/200) op verborgen testgevallen
Een eenvoudige heuristiek gebaseerd op de lengte van de titel, het aantal spaties en gebruik van het -ly
achtervoegsel.
isOnion = str => str.length ** 0.25 + str.split(" ").length ** 1.25 * 2 + str.split(/ly\b/).length ** 1.75 * 7 > 76
Reacties
- Dit is absurd effectief gezien hoe eenvoudig het is.
- Deze oplossing scoorde 63,5% op de verborgen testgevallen, dus het is geldig.
- Niet zo eenvoudig als mogelijk was in het begin van de sandbox (100%, gebruikmakend van verschillen in hoofdlettergebruik voordat het werd gestandaardiseerd) maar dit is heel eenvoudig.
- @Mego Gewoon uit nieuwsgierigheid, verbetert deze NSFW-versie de score op de verborgen testgevallen? 🙂
- @Arnauld 66% met die versie
Antwoord
Python 3, 84%
Ongetest op verborgen testgevallen.
Dit maakt gebruik van Keras LSTM RNN die is getraind op verschillende koppen. Om het uit te voeren heb je Keras het volgende nodig en het model dat ik “beschikbaar heb gemaakt op GitHub: repo-link . Je hebt het model en de woord / vectortoewijzingen bevinden zich in .pkl
. De laatste
De afhankelijkheden zijn:
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
De instellingen zijn:
max_headline_length = 70 word_count = 20740
Het model is:
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"))
Nu om het model en het woord embeddings te laden:
model.load_weights("model.h5") word_to_index = load(open("words.pkl", "rb"))
En de code om te testen of een string afkomstig is van “NotTheOnion” of “TheOnion “Ik” heb een snelle hulpfunctie geschreven die de string converteert naar de respectievelijke woordinsluitingen:
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
Uitleg
Deze code voert een model dat de relaties tussen woorden analyseert door de woorden voor te stellen als een “vector”. U kunt hier meer lezen over het insluiten van woorden.
Dit is getraind op koppen, maar de testcases zijn uitgesloten .
Dit proces is geautomatiseerd na behoorlijk wat verwerking. Ik heb de laatste verwerkte woordenlijst verdeeld als een .pkl
, maar wat er gebeurt bij het insluiten van woorden, is dat we eerst de zin analyseren en de woorden isoleren.
Daarna de woorden hebben, is de volgende stap om de verschillen en overeenkomsten tussen bepaalde woorden te begrijpen, bijvoorbeeld king
en queen
versus duke
en duchess
. Deze insluitingen gebeuren niet tussen de eigenlijke woorden, maar tussen getallen die de woorden vertegenwoordigen, wat is opgeslagen in de .pkl
bestand. Woorden die de machine “niet begrijpt” worden toegewezen aan een speciaal woord <UNK>
waardoor we kunnen begrijpen dat er een woord staat, maar dat het niet precies bekend is wat de betekenis is.
Nu de woorden begrepen kunnen worden, moet de volgorde van de woorden (kop) kunnen worden geanalyseerd. Dit is wat “LSTM” doet, een LTSM is een type “RNN” -cel die vermijdt het verdwijnende verloopeffect. Eenvoudiger gezegd: het duurt een reeks woorden en het stelt ons in staat relaties tussen de woorden te vinden.
Nu is de laatste laag Dense
wat in feite betekent dat het een soort array is, wat betekent dat de uitvoer er als volgt uitziet: [probability_is_not_onion, probability_is_onion]
. Door te bepalen welke groter is, kunnen we kiezen welke het meest betrouwbare resultaat is voor de gegeven kop.
Antwoord
Python 3 + Keras, 41/50 = 82%
83% (166/200) over verborgen testgevallen
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
en vocabulary.json
kunnen worden opgehaald uit hier (erg groot) en hier .
Volledig verbonden classificator verbonden met een vooraf getraind sentimentanalysemodel DeepMoji, dat bestaat uit gestapelde bidirectionele LSTMs en een aandachtsmechanisme. Ik bevroor de DeepMoji-lagen en haalde de laatste softmax-laag eruit, trainde alleen de volledig verbonden lagen, maakte vervolgens de DeepMoji-lagen los en trainde ze samen om ze te finetunen. Het aandachtsmechanisme is afkomstig van https://github.com/bfelbo/DeepMoji/blob/master/deepmoji/attlayer.py (ik wilde niet al hun code als afhankelijkheid gebruiken voor één klas, vooral omdat het Python 2 is en nogal onpraktisch om als module te gebruiken …)
Dit presteert verrassend slecht op de testset van Mego, gezien het feit dat het op mijn eigen grotere validatieset krijgt> 90%. Dus ik “ben hier nog niet klaar mee.
Reacties
- 83% op verborgen testgevallen, ervan uitgaande dat ik het correct heb uitgevoerd
Antwoord
JavaScript ( Node.js ), 98% (49/50)
96% (192/200) op verborgen testgevallen
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)); };
Dit vereist twee grote JSON-bestanden die ik “niet hier of op ” TiO . Download ze via de volgende links en sla ze op met de words.json
en namen, in dezelfde map als het JS-bestand. Er is ook een link voor een JS-bestand met testcases en resultaat / percentage afdrukken.U kunt uw verborgen testcases in variabelen onions
en nonOnions
plaatsen.
- words.json
- bags.json
- ui.js (dit omvat standaard testgevallen)
Na het opslaan van alle 3 bestanden in dezelfde map, voer je .
De O
functie retourneert true
als het ui en false
als het niet “t is. Gebruikt een grote lijst met woordtassen (zonder volgorde) om te detecteren of de invoertekenreeks ui is. Een beetje hard gecodeerd, maar werkt heel goed op verschillende willekeurige tests gevallen.
Opmerkingen
- Deze oplossing krijgt 96% op de verborgen testgevallen
Antwoord
Werken met Arnauld “s oplossing
JavaScript (ES6), 41/50
64% (128/200) op verborgen testcases
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) op verborgen testgevallen (ongeldig)
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
De lengte + aantal woorden + “ly “concept werkt redelijk goed, ik kon er nog een paar punten uit persen door het woord papa te zoeken (wanneer praten echte artikelen over de vaders van mensen in de derde persoon in de titel?) en een extra punt door te veranderen de “ly” zoekheuristiek en het controleren op de aanwezigheid van getallen in de titel (wat in het algemene geval buiten de test misschien minder geldig is, dus ik heb beide oplossingen achtergelaten)
Opmerkingen
- Ik weet niet ‘ van het vadergedeelte … lijkt een beetje op het optimaliseren van de testcase voor mij …
- En ja, ik kan tal van Not the Onion-artikelen vinden waarin vaders worden genoemd
- Daar ‘ is waarschijnlijk een betere manier om het te doen als onderdeel van de heuristiek en niet alleen een harde ” win ” als het dad bevat, maar ik stel me voor dat zelfs buiten de testdatabase abstract gesproken wordt over een specifieke ” Vader ” komt vaker voor op The Onion
- Je eerste oplossing scoorde 64% op de verborgen testgevallen, dus het is geldig. Uw tweede oplossing scoorde 62,5% op de verborgen testgevallen, dus het is niet geldig.
- @Mego Wat een kleine marge …
Your score will be the number of correct outputs divided by the total number of headlines
Is bytecount een gelijkspel?/ly\b/
die alleen werkt omdat de 25 Onio n koppen die je hebt gekozen, hebben toevallig meer bijwoorden, maar voor zover ik weet, zou je het gemakkelijk kunnen laten struikelen met een andere testbatterij. En wie ‘ is om te zeggen dat zijn coëfficiënten niet ‘ zijn gekozen om zijn score te optimaliseren? (Waarom zou hij ze niet ‘ optimaliseren?)brain.js
en LSTM, met voorbeelden in deze uitgave en 100 andere voorbeelden van elk type van verstrekte links, maar het resultaat was niet ‘ t goed genoeg met nieuwe titels die ‘ t aanwezig in trainingssets. Ik ‘ ben klaar: P