Chi è quella distribuzione di probabilità?


16

introduzione

In questa sfida, ti viene fornito un elenco di numeri in virgola mobile non negativi disegnati indipendentemente da una distribuzione di probabilità. Il tuo compito è inferire quella distribuzione dai numeri. Per rendere fattibile la sfida, hai solo cinque distribuzioni tra cui scegliere.

Si noti che tutte le distribuzioni di cui sopra hanno significato esattamente 1/2.

L'obiettivo

L'input è un array di numeri in virgola mobile non negativi, di lunghezza compresa tra 75 e 100 inclusi. L'output deve essere una delle lettere UTBEG, in base alla quale delle distribuzioni di cui sopra indovini i numeri.

Regole e punteggio

Puoi dare un programma completo o una funzione. Le scappatoie standard non sono ammesse.

In questo repository , ci sono cinque file di testo, uno per ogni distribuzione, ciascuno lungo esattamente 100 righe. Ogni riga contiene un elenco delimitato da virgole da 75 a 100 float disegnati indipendentemente dalla distribuzione e troncati a 7 cifre dopo il punto decimale. È possibile modificare i delimitatori in modo che corrispondano al formato dell'array nativo della propria lingua. Per qualificarsi come risposta, il programma deve classificare correttamente almeno 50 elenchi per ciascun file . Il punteggio di una risposta valida è il conteggio dei byte + il numero totale di elenchi classificati erroneamente . Vince il punteggio più basso.


Probabilmente avrei dovuto chiedere prima, ma quanta ottimizzazione è prevista per i casi di test? Sono in un punto in cui posso migliorare il mio punteggio modificando alcuni parametri, ma l'impatto sul punteggio dipenderà probabilmente dai casi di test indicati.
Dennis,

2
@Dennis Puoi ottimizzare quanto vuoi, i casi di test sono una parte fissa della sfida.
Zgarb,

YU NO Distribuzione Student-t? = (
N3buchadnezzar,

Risposte:


6

Julia, 60 62 byte + 25 2 errori = 82 64

k->"EGTBU"[(V=std(k);any(k.>1)?V>.34?1:2:V<.236?3:V>.315?4:5)]

Questo è abbastanza semplice. La varianza per le distribuzioni è per lo più diversa: 1/4 per esponenziale, 1/8 per beta, 1/12 per gamma e uniforme e 1/24 per triangolare. Pertanto, se utilizziamo la varianza (qui eseguita utilizzando la stddeviazione standard, la radice quadrata della varianza) per determinare la probabile distribuzione, dobbiamo solo fare di più per distinguere la gamma dall'uniforme; per questo, cerchiamo un valore maggiore di 1 (usando any(k.>1)) - detto questo, facciamo il controllo sia esponenziale che gamma, poiché migliora le prestazioni complessive.

Per salvare un byte, indicizzando la stringa "EGTBU" viene eseguita anziché la valutazione diretta a una stringa all'interno dei condizionali.

Per i test, salvare i file txt in una directory (mantenendo i nomi così come sono) ed eseguire Julia REPL in quella directory. Quindi, associare la funzione a un nome come

f=k->"EGTBU"[(V=std(k);any(k.>1)?V>.34?1:2:V<.236?3:V>.315?4:5)]

e utilizzare il codice seguente per automatizzare il test (questo leggerà dal file, si convertirà in una matrice di array, utilizzerà la funzione e l'output per ogni mancata corrispondenza):

m=0;for S=["B","E","G","T","U"] K=open(S*".txt");F=readcsv(K);
M=Array{Float64,1}[];for i=1:100 push!(M,filter(j->j!="",F[i,:]))end;
close(K);n=0;
for i=1:100 f(M[i])!=S[1]&&(n+=1;println(i," "S,"->",f(M[i])," ",std(M[i])))end;
println(n);m+=n;end;println(m)

L'output sarà costituito da righe contenenti il ​​caso non corrispondente, la distribuzione corretta -> la distribuzione determinata e la varianza calcolata (ad es. 13 G->E 0.35008999281668357 Significa che la tredicesima riga in G.txt, che dovrebbe essere una distribuzione gamma, è determinata come esponenziale distribuzione, con la deviazione standard di 0,35008999 ...)

Dopo ogni file, genera anche il numero di disallineamenti per quel file, e alla fine mostra anche il totale degli abbinamenti (e dovrebbe leggere 2 se eseguito come sopra). Per inciso, dovrebbe avere 1 mancata corrispondenza per G.txt e 1 mancata corrispondenza per U.txt


7

R, 202 192 184 182 162 162 154 byte + 0 errori

function(x)c("U","T","B","E","G")[which.max(lapply(list(dunif(x),sapply(x,function(y)max(0,2-4*abs(.5-y))),dbeta(x,.5,.5),dexp(x,2),dgamma(x,3,6)),prod))]

Questo si basa sulla formula bayesiana P (D = d | X = x) = P (X = x | D = d) * P (D = d) / P (X = x), dove D è la distribuzione e X è il campione casuale. Scegliamo d in modo che P (D = d | X = x) sia il maggiore di 5.

Assumo un precedente piatto (cioè P (D = di) = 1/5 per i in [1,5]), il che significa che P (D = d) nel numeratore è lo stesso in tutti i casi (e il denominatore sarebbe essere sempre lo stesso in tutti i casi), quindi possiamo scartare tutto tranne P (x = X | D = d), che (ad eccezione della distribuzione triangolare) semplifica le funzioni native in R.

ungolfed:

function(x){
  u=prod(dunif(x))
  r=prod(sapply(x,function(y)max(0,2-4*abs(.5-y))))
  b=prod(dbeta(x,.5,.5))
  e=prod(dexp(x,2))
  g=prod(dgamma(x,3,6))
  den=.2*u+.2*r+.2*b+.2*e+.2*g
  c("U","T","B","E","G")[which.max(c(u*.2/den,r*.2/den,b*.2/den,e*.2/den,g*.2/den))]
}

Si noti che la versione non golfata non è esattamente equivalente alla versione golfizzata poiché la rimozione del denominatore evita il caso di Inf / Inf che si verifica se si consente alla distribuzione beta di superare l'intervallo chiuso [0,1] anziché (0, 1) - come fanno i dati di esempio. Un'istruzione if aggiuntiva lo gestirà, ma poiché è solo a scopo illustrativo, probabilmente non vale la pena aggiungere la complessità che non è al centro dell'algoritmo.

Grazie @Alex A. per ulteriori riduzioni del codice. Soprattutto per quale.max!


1
È possibile ottenere questo a 190 byte rimuovendo l'interruzione di riga dopo l'apertura {e quella prima della chiusura }e aliasing prod, ad esempio P=prod, quindi facendo P(dunif(x)), ecc. La funzione non ha bisogno di un nome per essere un invio valido, quindi è possibile rimuovere p=. Inoltre, ottimo lavoro. :)
Alex A.

2
Puoi farlo arrivare a 182 usando i suggerimenti sopra e usando which.max(c(u,r,b,e,g))al posto di c(u,r,b,e,g)==max(c(u,r,b,e,g)).
Alex A.

156:function(x){c("U","T","B","E","G")[which.max(lapply(list(dunif(x),sapply(x,function(y)max(0,2-4*abs(.5-y))),dbeta(x,.5,.5),dexp(x,2),dgamma(x,3,6)),prod))]}
Alex A.

Come osi usare R per una sfida che coinvolge le statistiche !!
Flawr

6

CJam, 76

{2f*__{(z.4<},,%,4e<"UBT"="EG"\*\$-2=i3e<=}

Il codice sorgente è lungo 43 byte e classifica erroneamente 33 elenchi.

Verifica

$ count()(sort | uniq -c | sort -nr)
$ cat score.cjam
qN%{',' er[~]
  {2f*__{(z.4<},,%,4e<"UBT"="EG"\*\$-2=i3e<=}
~N}/
$ for list in U T B E G; { echo $list; cjam score.cjam < $list.txt | count; }
U
     92 U
      6 B
      2 T
T
    100 T
B
     93 B
      7 U
E
     92 E
      8 G
G
     90 G
      6 E
      3 T
      1 U

Idea

Differenziare la distribuzione esponenziale e gamma da quelle rimanenti è facile, poiché sono le uniche distribuzioni che assumono valori maggiori di 1 .

Per decidere tra gamma , esponenziale e altri, diamo un'occhiata al secondo valore più alto del campione.

  • Se si trova in [1.5, ∞) , indoviniamo gamma .

  • Se risiede in [1, 1.5) , immaginiamo esponenziale .

  • Se si trova in [0, 1) , abbiamo tre possibilità rimanenti.

    Le distribuzioni rimanenti possono essere differenziate per la percentuale di valori del campione vicini alla media ( 0,5 ).

    Dividiamo la lunghezza del campione per il conteggio dei valori che rientrano in (0,3, 0,7) e diamo un'occhiata al quoziente risultante.

    • Se si trova in (1, 2] , immaginiamo triangolare .

    • Se sta in (2, 3] , immaginiamo l' uniforme .

    • Se si trova in (3, ∞) , immaginiamo beta .

Codice

2f*    e# Multiply all sample values by 2.
__     e# Push to copies of the sample.
{      e# Filter; for each (doubled) value in the sample:
  (z   e#   Subtract 1 and apply absolute value.
  .4<  e#   Check if the result is smaller than 0.4.
},     e# If it is, keep the value.
,/     e# Count the kept values (K).
%      e# Select every Kth value form the sample, starting with the first.
,      e# Compute the length of the resulting array.
       e# This performs ceiled division of the sample length by K.
4e<    e# Truncate the quotient at 4.
"UBT"= e# Select 'T' for 2, 'U' for 3 and 'B' for 4.
"EG"\* e# Place the selected character between 'E' and 'G'.
\$     e# Sort the remaining sample.
-2=i   e# Extract the second-highest (doubled) value and cast to integer.
3e<    e# Truncate the result at 3.
=      e# Select 'E' for 3, 'G' for 2 and the character from before for 1.

3

Matlab, 428 328 byte + 33 classificati erroneamente

Questo programma sta fondamentalmente confrontando il CDF reale con uno stimato dato i dati, e quindi calcolando la distanza media tra quei due: Penso che l'immagine spieghi di più:

inserisci qui la descrizione dell'immagine

I dati mostrati in questa immagine qui mostrano abbastanza chiaramente che appartiene alla distribuzione turchese, in quanto è abbastanza vicino a quello, quindi questo è fondamentalmente ciò che il mio programma sta facendo. Probabilmente può essere giocato a golf un po 'di più. Per me è stata prima di tutto una sfida concettuale, non molto da golf.

Questo approccio è anche indipendente dai pdf scelti, funzionerebbe per qualsiasi set di distribuzioni.

Il seguente codice (ungolfed) dovrebbe mostrare come è fatto. La versione golfizzata è di seguito.

function r=p(x);
data=sort(x(1:75));
%% cumulative probability distributiosn
fu=@(x)(0<x&x<1).*x+(1<=x).*1;
ft=@(x)(0<x&x< 0.5).* 2.*x.^2+(1-2*(1-x).^2).*(0.5<=x&x<1)+(1<=x);
fb=@(x)(0<x&x<1).*2.*asin(sqrt(x))/pi+(1<=x);
fe=@(x)(0<x).*(1-exp(-2*x));
fg=@(x)(0<x).*(1-exp(-x*6).*(1+x*6+1/2*(6*x).^2));
fdata = @(x)sum(bsxfun(@le,data,x.'),2).'/length(data);
f = {fe,fg,fu,ft,fb};
str='EGUTB';
%calculate distance to the different cdfs at each datapoint
for k=1:numel(f);
dist(k) = max(abs(f{k}(x)-fdata(x)));
end;
[~,i]=min(dist);
r=str(i);
end

Versione completamente giocata a golf:

function r=p(x);f={@(x)(0<x).*(1-exp(-2*x)),@(x)(0<x).*(1-exp(-x*6).*(1+x*6+18*x.^2)),@(x)(0<x&x<1).*x+(1<=x),@(x)(0<x&x<.5).*2.*x.^2+(1-2*(1-x).^2).*(.5<=x&x<1)+(1<=x),@(x)(0<x&x<1).*2.*asin(sqrt(x))/pi+(1<=x)};s='EGUTB';for k=1:5;d(k)=max(abs(f{k}(x)-sum(bsxfun(@le,x,x.'),2).'/nnz(x)));end;[~,i]=min(d(1:5-3*any(x>1)));r=s(i)

2

Perl, 119 byte + 8 classificazioni errate = 127

Ho preso un piccolo albero decisionale su tre caratteristiche:

  • $ o: booleano: se qualche campione> 1.0
  • $ t: conteggio: 0-meno meno 6-13-ile tagliato nell'intervallo 0-1,
  • $ h: conteggio: 0 ° meno 6 ° più 12 ° 13-ile tagliato nell'intervallo 0-1

Invocato con perl -F, -lane -e '...'. Non sono sicuro se dovrei aggiungere una penalità per i parametri non standard. Se le virgole fossero spazi, immagino che avrei potuto andarmene senza la -F,

per (@ F) {$ b [$ _ * 13] ++; $ o ++ se $ _> 1}
$ H = ($ t = $ b [0] - $ b [6]) + $ b [12];
print $ o ($ t> -2 "e": "g"?): ($ h = 19 "b":? "u")?);
$ O = @ b = ()

L'output leggermente formattato (senza il flag -l) è:

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    bbbbbbbbbbbbbbbbbbbbbbbbubbbbbbbbbbbbbbbbbbbbbbb
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
    eeegeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
gggggggegggggggggggggggggggggggggggggggggggggggggggg
    gggggggggggggggggggggggggggggggggggggggggggggggg
tttttttttttttttttttttttttttttttttttttttttttttttttttt
    ttttttttttttttttttttttttttttuttttttttttttutttttt
uuuuuuuuuuuuuuuuuuuuuuuuuuutuuuuuuuuuuuuuuuubuuuuuuu
    uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuutuuuu

0

Python, 318 byte + 35 errori di classificazione

from scipy.stats import*
from numpy import*
def f(l):
    r={'U':kstest(l,'uniform')[1],'T':kstest(l,'triang',args=(.5,))[1],'B':kstest(l,'beta',args=(.5,.5))[1],'E':kstest(l,'expon',args=(0,.5,))[1],'G':kstest(l,'gamma',args=(3,0,1/6.0))[1]}
    if sum([x>1 for x in l]): r['U'],r['T'],r['B']=0,0,0
    return max(r,key=r.get)

Idea: la distribuzione è indovinata in base al valore p del test di Kolmogorov-Smirnov.

Test

from scipy.stats import*
from numpy import*
import os
from io import StringIO
dir=os.path.dirname(os.path.abspath(__file__))+"/random-data-master/"

def f(l):
    r={'U':kstest(l,'uniform')[1],'T':kstest(l,'triang',args=(.5,))[1],'B':kstest(l,'beta',args=(.5,.5))[1],'E':kstest(l,'expon',args=(0,.5,))[1],'G':kstest(l,'gamma',args=(3,0,1/6.0))[1]}
    if sum([x>1 for x in l]): r['U'],r['T'],r['B']=0,0,0
    return max(r,key=r.get)

U=[line.rstrip('\n').split(',') for line in open(dir+'U.txt')]
U=[[float(x) for x in r] for r in U]
T=[line.rstrip('\n').split(',') for line in open(dir+'T.txt')]
T=[[float(x) for x in r] for r in T]
B=[line.rstrip('\n').split(',') for line in open(dir+'B.txt')]
B=[[float(x) for x in r] for r in B]
E=[line.rstrip('\n').split(',') for line in open(dir+'E.txt')]
E=[[float(x) for x in r] for r in E]
G=[line.rstrip('\n').split(',') for line in open(dir+'G.txt')]
G=[[float(x) for x in r] for r in G]

i,_u,_t,_b,_e,_g=0,0,0,0,0,0
for u,t,b,e,g in zip(U,T,B,E,G):
    _u+=1 if f(u)=='U' else 0
    _t+=1 if f(t)=='T' else 0
    _b+=1 if f(b)=='B' else 0
    _e+=1 if f(e)=='E' else 0
    _g+=1 if f(g)=='G' else 0
    print f(u),f(t),f(b),f(e),f(g)
print _u,_t,_b,_e,_g,100*5-_u-_t-_b-_e-_g
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.