Cibule, nebo ne Cibule?

Cibule (upozornění: mnoho článků je NSFW) je satirická zpravodajská organizace, která paroduje tradiční zpravodajská média. V roce 2014 The Onion spustil satirický zpravodajský web ClickHole (upozornění: často také NSFW), který paroduje weby typu „clickbait“ jako BuzzFeed. Díky Poeovu zákonu je docela běžné, že si lidé přečtou titulky článků z The Onion nebo ClickHole a věří jim, že jsou pravdivé, nevědí že jsou zamýšleny jako satira. Konverzace se také děje se směšně znějícími skutečnými příběhy zpráv – lidé si často myslí, že jsou satiry, když nejsou.

Tento zmatek se přirozeně hodí ke hře – vzhledem k titulku zprávy zkuste uhodnout, zda nebo není to satira. Tato výzva je přesně to, jak to udělat s programem.

Vzhledem k novinovému nadpisu (řetězec skládající se pouze z tisknutelných znaků a mezer ASCII), výstup 1 pokud nadpis je satira, nebo 0 pokud tomu tak není. Vaše skóre bude počet správných výstupů děleno celkovým počtem nadpisů.

Jako obvykle, standardní mezery (zejména optimalizace pro testovací případy ) nejsou povoleny. Abych to vynutil, spustím vaše programy na sadě 200 skrytých testovacích případů (100 z The Onion, 100 z Not The Onion). Aby vaše řešení bylo platné, nesmí u veřejných testovacích případů zaznamenat o více než 20 procentních bodů méně, než je vaše skóre.

Testovací případy

Přijít s testovacími případy pro tuto výzvu , Vybral jsem 25 nadpisů z Cibule subreddit (kde jsou zveřejňovány články z Cibule a jejích podřízených webů, jako ClickHole) a 25 nadpisů z subreddit Not The Onion (kde jsou zveřejňovány skutečné zpravodajské články, které zní jako satira). Jediné změny, které jsem v nadpisech provedl, bylo nahrazení „vymyšlených“ uvozovek běžnými uvozovkami ASCII a standardizace velkých písmen – vše ostatní zůstane nezměněno oproti nadpisu původního článku. Každý nadpis je na svém vlastním řádku.

Cibulové titulky

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 

Komentáře

  • Your score will be the number of correct outputs divided by the total number of headlines Je bytecount rozdělovač kravat?
  • I ‚ trochu confused. Jaký druh řešení očekáváte? Každé řešení bude muset “ optimalizovat pro testovací případy “ poněkud omezit psaní AI, která dokáže rozumět anglicky a má smysl pro humor. Například řešení Arnauld ‚ detekuje /ly\b/ který funguje jen proto, že 25 Onio V nadpisech, které jste vybrali, je více adverbií, ale vím, že byste to mohli snadno vypustit s jinou testovací baterií. A kdo ‚ s říci, že jeho koeficienty nejsou ‚ vybrány k optimalizaci skóre? (Proč by je ‚ optimalizoval?)
  • Tato testovací baterie vypadá trochu neobvykle. Je to ‚ jako požádat o klasifikátor, který dokáže detekovat psy na fotografii, ale vaše případy pozitivních testů berete jako fotografie psů a případy negativních testů z článku Buzzfeed s názvem “ 25 fotek objektů ‚ ll Přísaháte, že jsou psi, ale ne, ukáže se, že nejsou ‚ t! (# 11 vám to vybuchne!) “ Ztěžuje to dost těžký problém.
  • Nejenže je výzva těžká, ale ‚ také není zřejmé (pro mě), jaký je ‚ rozdíl. Pokud to nedokážu ‚ t vyřešit, samozřejmě to můj program ‚ t vyřešit nedokáže (to znamená, když mě přesvědčí, že to ne ‚ t hardcode pro testovací případy)
  • No, strávil jsem +36 hodin trénováním umělé neuronové sítě pomocí brain.js a LSTM se vzorky v tomto čísle a 100 dalšími vzorky každého typu z poskytnutých odkazů, ale výsledek nebyl ‚ dost dobrý s novými tituly, které nebyly ‚ není přítomen v tréninkových sadách. ‚ hotovo: P

odpověď

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

63,5% (127/200) u skrytých testovacích případů

Jednoduchá heuristika založená na délce názvu, počtu mezer a použití přípony -ly.

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

Vyzkoušejte to online!

Komentáře

  • To je absurdně efektivní pro to, jak jednoduché je.
  • Toto řešení dosáhlo 63,5% skryté testovací případy, takže je to platné.
  • Není to tak jednoduché, jak to bylo možné na začátku karantény (100%, s využitím kapitalizačních rozdílů před standardizací), ale je to opravdu jednoduché.
  • @Mego Z důvodu zvědavosti vylepšuje tato verze NSFW skóre u skrytých testovacích případů? 🙂
  • @Arnauld 66% s touto verzí

odpověď

Python 3, 84%

Nevyzkoušeno na skrytých testovacích případech.

Používá se Keras LSTM RNN trénovaný na různých nadpisech. Chcete-li jej spustit, potřebujete Keras následující a model, který jsem „zpřístupnil na GitHubu: repo odkaz . Budete potřebovat model .h5 a mapování slov / vektorů jsou v .pkl. Nejnovější

Závislosti jsou:

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 

Nastavení jsou:

max_headline_length = 70 word_count = 20740 

Model je:

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

Nyní načtěte model a vkládání slov:

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

A kód pro testování, zda řetězec pochází z „NotTheOnion“ nebo „TheOnion „Napsal jsem rychlou pomocnou funkci, která převádí řetězec na příslušné vkládání slov:

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 

Vysvětlení

Tento kód spouští model, který analyzuje vztahy mezi slovy reprezentováním slov jako „vektoru“. Další informace o vkládání slov naleznete zde .

Toto je procvičeno v nadpisech, ale testovací případy jsou vyloučeny .

Tyto procesy jsou automatizovány po docela dost zpracování. Distribuoval jsem konečný seznam zpracovaných slov jako .pkl, ale co se stane při vkládání slov, je nejdříve analyzovat větu a izolovat slova.

Poté, co nyní mít slova, dalším krokem je schopnost porozumět rozdílům a podobnostem mezi určitými slovy, např. king a queen versus duke a duchess. Tato vložení se nestávají mezi skutečnými slovy, ale mezi čísly představujícími slova, což je to, co je uloženo v .pkl soubor. Slova, kterým stroj nerozumí, jsou mapována na speciální slovo <UNK>, které nám umožňuje pochopit, že tam slovo je, ale že není přesně známo, co to znamená.

Nyní, když je slovům rozumět, je třeba analyzovat posloupnost slov (nadpis). To dělá „LSTM“, LTSM je typ buňky „RNN“, která vyhýbá se efektu mizejícího přechodu. Jednodušší je, že zabírá sekvenci slov a umožňuje nám najít mezi nimi vztahy.

Poslední vrstva je Dense což v podstatě znamená, že je to jako pole, což znamená, že výstup je jako: [probability_is_not_onion, probability_is_onion]. Když zjistíme, který z nich je větší, můžeme si vybrat, který z nich je nejspolehlivějším výsledkem daného nadpisu.

Odpověď

Python 3 + Keras, 41/50 = 82%

83% (166/200) u skrytých testovacích případů

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 a vocabulary.json lze načíst zde (velmi velké) a zde .

Plně připojený klasifikátor připojený k předem vyškolenému modelu analýzy sentimentu DeepMoji, který se skládá ze skládaných obousměrných LSTM a mechanismu pozornosti. Zmrazil jsem vrstvy DeepMoji a vytáhl finální vrstvu softmaxu, trénoval jen plně spojené vrstvy, poté zmrazil vrstvy DeepMoji a trénoval je společně pro finetuning. Mechanismus pozornosti je převzat z https://github.com/bfelbo/DeepMoji/blob/master/deepmoji/attlayer.py (nechtěl jsem použít celý svůj kód jako závislost pro jednu třídu, zejména proto, že je to Python 2 a je poměrně nepraktický použít jako modul …)

Na testovací sadě Mego to funguje překvapivě špatně, vzhledem k tomu, že na mé vlastní větší validaci to nastavím dostane> 90%. Takže s tím ještě nejsem hotový.

Komentáře

  • 83% u skrytých testovacích případů, za předpokladu, že jsem to spustil správně

Odpověď

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

96% (192/200) u skrytých testovacích případů

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

To vyžaduje dva velké soubory JSON, které je nemohu umístit sem ani na “ TiO „. Stáhněte si je z následujících odkazů a uložte je pomocí words.json a názvy, ve stejné složce jako soubor JS. K dispozici je také odkaz na soubor JS s testovacími případy a výsledkem / procentem tisku.Skryté testovací případy můžete vložit do proměnných onions a nonOnions.

Po uložení všech 3 souborů do stejného adresáře spusťte node onion.js.

Funkce O vrátí true, pokud se jedná o cibuli a false pokud to není. t. Používá velký seznam slovních tašek (bez pořadí), aby zjistil, zda je vstupní řetězec cibule. Druh pevně zakódovaný, ale velmi dobře funguje na různých náhodných testech případy.

Komentáře

  • Toto řešení získá 96% u skrytých testovacích případů

Odpověď

Vypracování řešení společnosti Arnauld

JavaScript (ES6), 41/50

64% (128/200) při skrytém testovací případy

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) ve skrytých testovacích případech (neplatné)

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 

Délka + počet slov + „ly „koncept funguje docela dobře, dokázal jsem zmáčknout několik dalších bodů kontrolou slova„ Tati “(kdy skutečné články hovoří o otcích lidí ve třetí osobě v názvu?) a další bod změnou heuristika vyhledávání „ly“ a kontrola přítomnosti čísel v názvu (což může být obecně méně platné mimo test, takže jsem obě řešení nechal)

Komentáře

  • Nevím ‚ nevím o otcovské části … zdá se mi to trochu jako optimalizovat testovací případ …
  • A ano, najdu spoustu článků Not The Onion zmiňujících táty
  • Existuje ‚ pravděpodobně lepší způsob, jak to udělat jako součást heuristiky a nejen tvrdé “ vyhrajte “ pokud obsahuje otce, ale představuji si, že i mimo testovací databázi abstraktně mluvím o konkrétním “ Táta “ je častější u The Onion
  • Vaše první řešení dosáhlo 64% u skrytých testovacích případů, takže je platné. Vaše druhé řešení dosáhlo u skrytých testovacích případů 62,5%, takže není platné.
  • @Mego Jaká těsná marže …

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *