de Kirill Dubovikov

Cum să obțineți un eșantion de subset aleatoriu rapid jenant cu Python

Cum sa obtineti un esantion de subset aleatoriu rapid jenant

Imaginați-vă că dezvoltați un model de învățare automată pentru a clasifica articolele. Ați reușit să obțineți un fișier text nerezonabil de mare, care conține milioane de identificatori de articole similare care aparțin aceleiași clase. Nu sunteți sigur dacă identificatorii care sunt apropiați unul de celălalt sunt independenți.

De exemplu, un analizor ar putea scrie împreună identificatori de articole de pe un singur site. Deci, acum doriți să obțineți un număr mare de eșantioane aleatorii dintr-o serie de câteva milioane de elemente pentru a crea un set de date de antrenament sau pentru a număra unele statistici empirice. Această situație poate apărea în practică mai des decât credeți.

Mulțumită lui Binder, poți joacă-te cu codul online fără a instala nimic local. Sau puteți clona Depozit Github. Vă rugăm să rețineți că toate criteriile de referință pot diferi de la o mașină la alta.

Ei bine, ce se întâmplă? Să folosim neclintit!

Pe Macbook Pro, acest cod rulează pentru în jur de 1,4 secunde pe buclă. Dacă doriți să obțineți 100.000 de probe, va dura aproximativ o zi și jumătate. Vai!

Mergând la viteză ☄️

Ce s-a întâmplat acolo? Pentru a genera un eșantion aleatoriu, numpy.random.choice permite matricea de fiecare dată când o numim. Când dimensiunea eșantionului nostru este doar o fracțiune din întreaga lungime a matricei, nu este nevoie să amestecăm matricea de fiecare dată când dorim să prelevăm o mostră. Să-l amestecăm o singură dată și să luăm mostre de la începutul matricei amestecate.

Când ajungem la ultimul element, trebuie să-l amestecăm din nou. Această optimizare are, de asemenea, un efect secundar foarte frumos: vom avea mai puține coliziuni (repetarea probelor).

Acum este timpul să codificăm acest lucru:

De data aceasta obținem 21,1 µs ± 979 ns pe buclă, care este mai rapid cu mai multe ordine de mărime.

Și mai rapid? ?

1611517745 792 Cum sa obtineti un esantion de subset aleatoriu rapid jenant

O putem face și mai repede? Da, dar trebuie să devenim nativi. Cython traduce codul Python în C sau C ++ nativ optimizat, care poate fi compilat și folosit ca un modul Python prietenos și familiar după aceea.

Puteți juca cu Cython în caietele Jupyter încărcând extensia Cython cu %load_ext Cython , și folosind %%cython magia ca prima afirmație dintr-o celulă cu cod Cython.

Aproape tot codul Python este cod Cython valid. Dar, pentru a profita la maximum, trebuie să folosim extensiile furnizate de Cython:

  • Adnotăm static toate tipurile pentru semnăturile funcției și definiția variabilelor pentru a utiliza variabile native C în loc de obiecte Python lente, acolo unde este posibil
  • Folosim un cdef cuvânt cheie pentru funcții care nu trebuie exportate ca API Python. cdef apelurile sunt mult mai rapide.
  • Dezactivăm indexarea negativă și verificarea limitelor matricei cu @cython.wraparoundși @cython.boundscheck pentru a obține mai multă viteză

Această refactorizare minoră este suficientă pentru a obține o accelerare rezonabilă (2x pe laptopul meu) în comparație cu versiunea Python.

Sunt obligat să spun că Cython este mult mai mult decât un traducător Python-C optimizat. Cu acest instrument minunat puteți, de asemenea:

Dar coliziuni? ?

Coliziunile de eșantionare apar atunci când obținem un element care se repetă în timp ce eșantionăm matricea. Pentru simplitate, să presupunem că matricea nu conține duplicate.

Vom compara cei doi algoritmi în ceea ce privește coliziunile. Putem colecta un număr mare de eșantioane din aceeași matrice pentru fiecare dintre algoritmi și apoi numărăm numărul total de coliziuni.

Când repetăm ​​acest proces de mai multe ori și înregistrăm rezultatele, colectăm de fapt un eșantion aleatoriu de numărări de coliziuni pentru ambii algoritmi.

Având la îndemână aceste mostre, putem aplica statistici pentru a le compara. În acest caz, vom folosi un test t (puteți citi mai multe despre distribuția t în my postarea anterioară și mai multe despre testul t aici).

Valoarea p pe care o obținem este 0, ceea ce înseamnă că rezultatul obținut este semnificativ.

Să facem un complot și să vedem diferența:

1611517745 501 Cum sa obtineti un esantion de subset aleatoriu rapid jenant

După cum puteți vedea, obținem un număr mult mai mic de coliziuni ca bonus.

Concluzie

Mulțumesc mult că l-ai citit până la capăt! Dă-mi câteva palme? dacă ați găsit acest material util – vă va ajuta să răspândiți vestea.