Stvaranje vjerodostojnih Tinder profila pomoću AI: Adversarne i rekurentne neuronske mreže u stvaranju multimodalnog sadržaja

Ovo je uređeni članak temeljen na originalnoj publikaciji, koji je uklonjen zbog rizika od privatnosti stvorenih korištenjem skupa podataka Tinder Kaggle profila podataka. Ovo je sada zamijenjeno podacima općih pregleda vina u svrhu demonstracije. GradientCrescent ne odobrava upotrebu neetički stečenih podataka.

Uvod

U proteklih nekoliko članaka proveli smo vrijeme pokrivajući dvije posebnosti generativnih arhitektura dubokog učenja koje pokrivaju stvaranje slika i teksta, koristeći generativne adversarne mreže (GAN) i ponavljajuće neuronske mreže (RNN). Odlučili smo ih predstaviti odvojeno kako bismo detaljno objasnili njihove principe, arhitekturu i Python implementacije. S obje mreže upoznate, odlučili smo prikazati složeni projekt s jakim aplikacijama u stvarnom svijetu, naime, stvaranje vjerodostojnih profila za aplikacije za druženje poput Tinder-a.

Lažni profili predstavljaju značajno pitanje na društvenim mrežama - mogu utjecati na javni diskurs, optužiti slavne osobe ili oboriti institucije. Samo je Facebook uklonio preko 580 milijuna profila samo u prvom tromjesečju 2018., dok je Twitter ukinuo 70 milijuna računa od svibnja do lipnja 2018. godine.

Na aplikacijama za druženje poput Tinder-a oslanjajući se na želju za povezivanjem s atraktivnim članovima, takvi profili mogu dovesti do ozbiljnih financijskih posljedica za žrtve koje ne sumnjaju. Srećom, većina njih još uvijek se može otkriti vizualnim pregledom, jer često sadrže slike niske rezolucije i slabo ili slabo naseljen bios. Uz to, kako je većina lažnih fotografija profila ukradena s legitimnih računa, postoji mogućnost poznavanja slika u stvarnom svijetu što dovodi do bržeg otkrivanja i brisanja lažnih računa.

Najbolji način borbe protiv prijetnje je razumijevanje. U prilog tome, igrajmo se vražjeg zagovornika i zapitajmo se: može li stvoriti pomični lažni Tinder profil? Možemo li stvoriti realnu reprezentaciju i karakterizaciju osobe koja ne postoji? Da biste bolje razumjeli izazov, pogledajmo nekoliko lažnih primjera ženskih profila iz Zooskinih „primjera internetskog profila za žene“:

Iz gornjih profila možemo promatrati neke zajedničke zajedničke značajke, naime, prisutnost jasne slike lica, zajedno s tekstualnim bio odjeljkom koji se sastoji od više opisnih i relativno kratkih fraza. Primijetit ćete da su, zbog umjetnih ograničenja biološke duljine, ove fraze često međusobno neovisne u pogledu sadržaja, što znači da prevladavajuća tema možda ne postoji u jednom odlomku. Ovo je savršeno za generiranje sadržaja temeljeno na AI.

Srećom, već posjedujemo komponente potrebne za izgradnju savršenog profila - naime StyleGANs i RNN. Raščlanit ćemo pojedinačne doprinose naših komponenti obučenih u Google suradničkom GPU okruženju, prije nego što sastavimo kompletan završni profil. Preskočit ćemo teoriju koja se nalazi iza obje komponente jer smo to objavili u njihovim vodičima za koje vas preporučujemo da se osvježite kao brzo osvježenje.

izvršenje

Izrada slika - StyleGAN

Ukratko, StyleGANs su podvrsta Generative Adversarial Network stvorena od NVIDIA tima dizajniranog za proizvodnju visokih i realističnih slika generiranjem različitih detalja u različitim rezolucijama kako bi se omogućila kontrola pojedinačnih značajki uz održavanje veće brzine treninga. Prethodno smo pokrivali njihovu upotrebu u stvaranju umjetničkih predsjedničkih portreta koje ohrabrujemo čitatelja da ponovno pogleda.

Za ovaj ćemo udžbenik koristiti arhitekturu NVIDIA StyleGAN, prethodno osposobljenu na skupu podataka otvorenog koda Flicker FFHQ lica, koja sadrži preko 70 000 lica rezolucije 102⁴², kako bismo stvorili realistične portrete za korištenje u našim profilima pomoću Tensorflowa.

U interesu vremena, koristit ćemo modificiranu verziju NVIDIA unaprijed obučene mreže za generiranje naših slika. Naša je bilježnica dostupna ovdje. Da zaključimo, kloniramo NVIDIA StyleGAN spremište, prije učitavanja tri jezgrene mrežne komponente StyleGAN (karras2019stylegan-ffhq-1024x1024.pkl), naime:

  • Trenutni memorijski snimak generatora
  • Trenutni snimak sjećanja na diskriminatora
  • Dugoročni prosjek generatora koji teži pružanju kvalitetnijih rezultata od trenutnih kolega.

Nakon inicijalizacije naše Tensorflow sesije započinjemo s ubacivanjem u naš unaprijed obučeni model.

# Učitajte unaprijed osposobljenu mrežu. url = 'https://drive.google.com/uc?id=1MEGjdvVpUsu1jB4zrXZN7Y4kBBOzizDQ' # karras2019stylegan-ffhq-1024x1024.pkl
s dnnlib.util.open_url (url, cache_dir = config.cache_dir) kao f: _G, _D, Gs = pickle.load (f)
# _G = Trenutni snimak generatora. Glavno je korisno za nastavak prethodnog treninga. # _D = trenutni snimak diskriminatora. Glavno je korisno za nastavak prethodnog treninga. # Gs = Dugoročni prosjek generatora. Prinosi su kvalitetniji od trenutnog snimanja.

Zatim nasumično sejemo latentni vektor (latentni), koji možete zamisliti kao komprimirani nacrt slike, koji ćemo koristiti kao naš ulaz za SyleGAN generator. Zatim pokrećemo generator zajedno s raznim argumentima poboljšanja kvalitete i spremamo sliku na uporabu:

za i u rasponu (1,20): rnd = np.random.RandomState (5) latents = rnd.randn (i, Gs.input_shape [1])
# Generiranje slike. fmt = dict (func = tflib.convert_images_to_uint8, nchw_to_nhwc = Istina) slike = Gs.run (kasno, nijedno, skraćenje_psi = 0,7, randomize_noise = Istina, izlaz_transform = fmt)
# Spremiti sliku. os.makedirs (config.result_dir, postoji_ok = Istina) png_filename = os.path.join (config.result_dir, 'example' + str (i) + '. png') PIL.Image.fromarray (slike [0], ' RGB "). spasi (png_filename)

Izlazne slike naći ćete u mapi s rezultatima. Ispod je prikazan kolaž primjera:

Primjeri izlaznih slika generiranih pomoću prethodno obučene mreže FFHQ

Najimpresivniji. Dok generirate više slika, hajde da poradimo na biografiji!

Stvaranje teksta - RNN

Ukratko, RNN-ovi su vrsta neuronske mreže koja je dizajnirana za rukovanje sekvencama širenjem informacija o svakom prethodnom elementu u nizu radi donošenja prediktivne odluke o sljedećem elementu niza. Prethodno smo pokrili njihovu upotrebu u analizi sentimenata teksta, što ohrabrujemo čitatelja da ponovo pogleda.

Za ovaj će vodič stvoriti jednostavnu RNN arhitekturu koja se temelji na sekvenci znakova u Kerasu, a koju ćemo obučiti na skupu podataka Kaggle Wine Reviews, koja sadrži prikupljene detalje od preko 15 000 recenzija vina, a koje će poslužiti za pružanje opisnog tekstualnog sadržaja za naše BIOS-a. U idealnom slučaju biste to zamijenili nekim predstavnikom skupa podataka tekstualnih domena korištenih na društvenim mrežama, ali one su uglavnom nedostupne za javnu upotrebu. Naše prijenosno računalo, koje se temelji na CharTrump implementaciji i Brownleeevom izvrsnom vodiču o RNN-ovima, dostupno je ovdje.

Započnimo uvozom svih naših standardnih paketa i preuzimanjem našeg skupa podataka:

#Uvoz svih paketa
import matplotlib.pyplot kao plt import seaborn kao sns import pandas kao pd import numpy kao np import string uvozno upozorenje import sklearn import io import scipy import numpy import json import nltk import sys import csv import os import os iz uvoza keras.models import Sequential from keras .plasti uvoze LSTM, odustajanje, aktivaciju, gustoću
! gdown https://drive.google.com/uc?id=1A8zyqs9j-kS1oE2xUhhFSRe0UGEtp_sc

S preuzetim skupom podataka pristupimo pregledima teksta svakog stupca definiranim stupcem 'opis' i definiramo osnovni vokabular znakova za našu mrežu. Oni predstavljaju znakove koje će naša mreža prepoznati i objaviti.

#Text uvoza i ponovne obrade base_dir = 'wine.csv'
tinder_profile_df = pd.read_excel (base_dir, error_bad_lines = Netačno, razgraničivač = '\ t')
# Ispis podataka okvira okvira tinder_profile_df.info ()
ispis (tinder_profile_df.head ())
# Ovo će ispisati broj redaka i stupaca koji će se koristiti za obuku ispisa ("Oblik vlaka:", tinder_profile_df.shape)
# Tinder_profile_df.head ()
# Konvertirajte okvir podataka u niz već ovdje
tinder_bios_df = tinder_profile_df [ 'opis']. primjenjivati ​​(str)
# Ispiši samo opise #print (tinder_bios_df)
# Definirajte generički vokabular # generički vokabularni znakovi = popis (string.printable) znakova.remove ('\ x0b') znakova.remove ('\ x0c')
VOCABULARY_SIZE = len (znakovi) znakovi_to_ix = {c: i za i, c u nabrajanju (znakova)} ispis ("vokabular len =% d"% VOCABULARY_SIZE) ispis (znakovi)

Da bismo stvorili svoje podatke o treningu, povezali bismo sve naše bio-informacije o profilu u dva velika niza sastavljena od manjih pojedinačnih fraza, koje predstavljaju naše skupove podataka o treningu i provjeri valjanosti (podijeljeno na omjer 80:20). Također ćemo ukloniti sve prazne profile i posebne znakove u postupku.

# Definiramo funkciju filtriranja prvi nosilac = [] za i u rasponu (0, len (tinder_bios_df)): #print (tinder_bios_df.iloc [i]); string = tinder_bios_df.iloc [i]
if (string == "nan"): ispis ("nan uklonjeno") else: hold.append (string)
#print (nositelj)
alphaholder = [] regex = re.compile ('[^ A-Za-z0–9 -.,]') #našto je držač spreman, uklanjamo sve ne alfanumeričke unose za i u rasponu (0, len (držač)) : string = hold [i] #Prvi parametar je zamjena, drugi parametar je vaš ulazni niz newstring = regex.sub ('', string)
alphaholder.append (newstring) #print (alfaholder)
#Split podataka u nizove vlaka i potvrde trainholder = [] validationholder = []
ispis (len (alfaholder)) # alfa držač alfa je 43660 za i u rasponu (0, 12000): Trainstring = alphaholder [i] trainholder.append (Trainstring) za i u rasponu (12000, len (alphaholder)): valstring = alphaholder [i] validationholder.append (valstring)
# Podaci su sada spremni, dodajte ih u ogromni niz finalstring = '' .join (trainholder) validationstring = '' .join (validationholder)
print (finalstring) ispis (validationstring)

Sa izvršenom prethodnom obradom, krenimo na izgradnju našeg modela. Započnimo s definiranjem naših hiperparametara. Parametri SEQUENCE_LEN i LAYER_COUNT predstavljaju veličinu ulazne sekvence i broj sloja mreže, te imaju izravan utjecaj na vrijeme treninga i čitljivost izlaza predviđanja.

Odabir 20 znakova i 4 sloja odabrani su kao dobar kompromis između brzine treninga i čitljivosti predviđanja. Srećom, kratka karakteristika naših ulaznih biorazgovora čini 20 znakova odličnim izborom, ali slobodno iskušajte i druge duljine.

Pored toga, definirajmo funkcije koje će opisati i opskrbiti naše mreže ulaznih podataka našoj mreži.

N_GPU = 1 SEQUENCE_LEN = 20; #Ovo je dužina znakova svakog pojedinog niza # U osnovi, koristimo 60 znakova da predvidimo 61. znak. Ovo nam mora biti kraće BATCH_SIZE = 512 # Broj nastavka hranjenih odjednom u paketu EPOCHS = 13 HIDDEN_LAYERS_DIM = 512 LAYER_COUNT = 4 DROPOUT = 0,2
text_train_len = len (finalstring) text_val_len = len (validationstring) def define_batch (X, y, sample = 3): "" "Opišite u ljudskom čitljivom obliku neke uzorke iz serije. Prikaži sljedeći znak s prethodnim znakom "" "za i u rasponu (uzorci): rečenica =" "za s u rasponu (SEQUENCE_LEN): rečenica + = znakovi [X [i, s,:]. Argmax ()] next_char = znakova [y [i,:]. argmax ()] ispis ("uzorak #% d: ...% s -> '% s" "% (i, rečenica [-20:], next_char)) def batch_generator (tekst, brojanje): "" "Generiranje serija za trening" "" dok je Istina: za batch_ix u rasponu (broji): X = np.zeros ((BATCH_SIZE, SEQUENCE_LEN, VOCABULARY_SIZE)) y = np.zeros ((BATCH_SIZE, VOCABULARY_SIZE))
batch_offset = BATCH_SIZE * batch_ix
za sample_ix u rasponu (BATCH_SIZE): sample_start = batch_offset + sample_ix za s u rasponu (SEQUENCE_LEN): X [sample_ix, s, karakteri_to_ix [tekst [sample_start + s]]] = 1 y [sample_ix, character_to_ix [text [sample_start + s 1]]] = 1
prinos X, y
za ix, (X, y) u nabrajanju (batch_generator (finalstring, count = 1)): # opisati neke uzorke iz prve serije Opis_batch (X, y, uzorci = 5) prijelom

Na kraju, definirajmo našu arhitekturu koja se sastoji od više uzastopnih dugoročnih memorija (LSTM) i slojeva odustajanja kao što je definirano parametrom LAYER_COUNT. Slaganje više LSTM slojeva pomaže mreži da bolje shvati složenost jezika u skupu podataka, jer svaki sloj može stvoriti složeniji reprezentativni prikaz rezultata iz prethodnog sloja u svakom vremenskom koraku. Otpadni slojevi pomažu u sprječavanju prekomjernog namještanja uklanjanjem dijela aktivnih čvorova iz svakog sloja tijekom treninga (ali ne tijekom predviđanja).

### Od aduta za izgradnju graničnika unaprijed def build_model (gpu_count = 1): "" "Izradite Kerasov slijedni model za obuku char-rnn" "" modela = Sekvencijalni () za i u dometu (LAYER_COUNT): model.add (LSTM (HIDDEN_LAYERS_DIM, return_sequences = Točno ako je (i! = (LAYER_COUNT-1)) else False, input_shape = (SEQUENCE_LEN, VOCABULARY_SIZE),)) model.add (Dropout (DROPOUT)) model.add (Gusta (VOCABULARY_SIZ). dodavanje (aktivacija ('softmax')) #removiran je multigpu line model.compile (gubitak = 'kategorija_crossentropy', optimizator = 'adam') povratni model
training_model = build_model (gpu_count = N_GPU)
train_batch_count = (text_train_len - SEQUENCE_LEN) // BATCH_SIZE val_batch_count = (text_val_len - SEQUENCE_LEN) // BATCH_SIZE ispis ("broj učiteljske serije:% d"% train_batch_count) ispis ("potvrda broja serije:% d"% val_b)

Sa tim završenim obučimo našu mrežu kroz 10 epoha i spremimo našu mrežu za buduću upotrebu. Budući da je naš skup podataka relativno nedosljedan zbog velikog broja različitih pregleda, tradicionalni parametri za mjerenje napretka kao što su točnost ili gubitak samo su za nas indikativni, ali grafikon gubitka tijekom epoha prikazan je u nastavku zbog potpunosti.

povijest = training_model.fit_generator (batch_generator (finalstring, count = train_batch_count), train_batch_count, max_queue_size = 1, # ne više od jedne serije u redu epohe = EPOCHS, validation_data = batch_generator (validationstring, count = val_batchte = 0)
training_model.save ( 'basic_LSTM_tindergenv1_4layers_20char_wine.h5')
Gubitak treninga i validacije naših RNN-a tijekom 13 epoha

Pomoću naše mreže obučeni ćemo generirati neke lažne biografije koristeći različite sjemenske riječi.

Korištenje sementičke fraze „Ovo“ daje ulomke poput:

  • [Ovo] je ukusno voćno vino finog rezanog zrelog voća i tanina. Pijte sada.
  • [Ovo] je svijetlo, čisto i lagano drveno vino. Nepce je tanko i blago začinjeno, s dozom tostiranog hrasta.

Korištenje sjemenske fraze „Lovely“ daje ulomke poput:

  • [Lijepo] i mekano, s hrskavom kiselinom. Kiselost je meka i svježa, nudi intenzivnu kiselost i ljute arome začina koji su sve završni.
  • [Lijepo] i gotovo glatko, s dozom koprive i limunovim koricama.

Uopće nije loše, iako možete reći da će se, kako se predviđanja nastavljaju, slabiti, a to se može pripisati mreži koja crpi mnoštvo recenzenata različitih stilova. Dulja duljina rečenica koja se nalaze u skupu podataka za pregled također djeluje u skladu s našim modelom. Slobodno isprobajte druge sjemenske izraze u bilježnici.

Kompletni profili

Za kraj, zaključimo izgradnju nekoliko cjelovitih lažnih profila. U interesu vremena, rezultate ćemo zalijepiti izravno na tri prethodno prikazana profila. Lako biste mogli izgraditi slučajni generator sjemena da biste generirali raspon dobi i imena.

S obzirom na ograničenja naših biografskih podataka, naši rezultati izgledaju nevjerojatno vjerodostojno, ili trebam reći brzi, s nekim dugotrajnim slabostima:

  • Sve su naše slike glave iz neposredne blizine naših subjekata. To je zbog prirode našeg skupa podataka i zahtjeva StyleGAN-a: primjeri treninga da zauzmu zajednički prostor značajki kako bi se generirale realne slike u istom stilu. Drugim riječima, imati fotografije osoba na kojima se može skijati zajedno s portretnim fotografijama dovelo bi do nerealnih rezultata.
  • Postoji samo jedna slika određenog pojedinca. Kako su svako sjeme i kombinacija stilova specifični za tu posebnu instancu stvaranja slika, izuzetno je teško voditi StyleGAN izlaz za generiranje više slika istog pojedinca, tj. Malo različitih kutova.
  • Slično tome, trenutno ne možemo selektivno kontrolirati dob i spol naših profila. To bi se moglo ispraviti prekvalifikacijom StyleGAN-a od nule pomoću prilagođenog skupa podataka, što bi zahtijevalo značajnu količinu resursa.

Sve u svemu, ovo je bila uspješna prezentacija sposobnosti AI u stvaranju vjerodostojnih ljudskih prikaza koristeći slobodno dostupne resurse. Buduća studija mogla bi uključivati ​​usporedbu razlika između stvarnih i generiranih profila i može li neuronska mreža znati razliku. Ali to je bitka za drugi dan.

Ako ste uživali u ovom članku, molimo razmislite o sljedećem GradientCrescentu! Sljedeće utvrđujemo je li neuronska mreža mogla predvidjeti financijsku krizu.

izvori

Karras et. al, skladište NVIDIA StyleGAN

Brownlee, generiranje teksta s ponavljajućim neuronskim mrežama LSTM-a u Pythonu s Kerasom

Testud, još jedan projekt generiranja teksta