2009-06-17 9 views
3

Pourriez-vous s'il vous plaît les gars s'il vous plaît dites-moi comment je peux rendre le code suivant plus pythonique?Comment rendre ce code plus pythonique?

Le code est correct. Divulgation complète - c'est problème 1b dans le document # 4 de this cours d'apprentissage automatique. Je suis censé utiliser l'algorithme de newton sur les deux ensembles de données pour ajuster une hypothèse logistique. Mais ils utilisent matlab & J'utilise scipy

Par exemple une question que j'ai est les matrices arrondies à des entiers jusqu'à ce que j'ai initialisé une valeur à 0.0. Y a-t-il un meilleur moyen?

Merci

import os.path 
import math 
from numpy import matrix 
from scipy.linalg import inv #, det, eig 

x = matrix('0.0;0;1' ) 
y = 11 
grad = matrix('0.0;0;0' ) 
hess = matrix('0.0,0,0;0,0,0;0,0,0') 
theta = matrix('0.0;0;0' ) 


# run until convergence=6or7 
for i in range(1, 6): 
    #reset 
    grad = matrix('0.0;0;0' ) 
    hess = matrix('0.0,0,0;0,0,0;0,0,0') 

    xfile = open("q1x.dat", "r") 
    yfile = open("q1y.dat", "r") 


    #over whole set=99 items 
    for i in range(1, 100):  
    xline = xfile.readline() 
    s= xline.split(" ") 
    x[0] = float(s[1]) 
    x[1] = float(s[2]) 
    y = float(yfile.readline()) 

    hypoth = 1/ (1+ math.exp(-(theta.transpose() * x))) 

    for j in range(0,3): 
     grad[j] = grad[j] + (y-hypoth)* x[j]  
     for k in range(0,3): 
     hess[j,k] = hess[j,k] - (hypoth *(1-hypoth)*x[j]*x[k]) 


    theta = theta - inv(hess)*grad #update theta after construction 

    xfile.close() 
    yfile.close() 

print "done" 
print theta 
+1

que fait la ligne y = 11? – SilentGhost

+0

qui définit le bit cool. – Geo

+0

+1 pour utiliser le mot pythonic dans une phrase. – samoz

Répondre

4
x = matrix([[0.],[0],[1]]) 
theta = matrix(zeros([3,1])) 
for i in range(5): 
    grad = matrix(zeros([3,1])) 
    hess = matrix(zeros([3,3])) 
    [xfile, yfile] = [open('q1'+a+'.dat', 'r') for a in 'xy'] 
    for xline, yline in zip(xfile, yfile): 
    x.transpose()[0,:2] = [map(float, xline.split(" ")[1:3])] 
    y = float(yline) 
    hypoth = 1/(1 + math.exp(theta.transpose() * x)) 
    grad += (y - hypoth) * x 
    hess -= hypoth * (1 - hypoth) * x * x.transpose() 
    theta += inv(hess) * grad 
print "done" 
print theta 
+1

Je ne sais pas, le code Quand il s'agit de matrices, il semble que ce soit un produit interne J'ai obtenu le code d'ici (http://www.scipy.org/SciPy_Tutorial) – MercerKernel

+0

@MercerKernel: cool - J'ai appris quelque chose de nouveau! des matrices m'a forcé à utiliser le point avec des matrices vous pouvez utiliser "*"! J'ai corrigé le code et je me suis également permis de faire theta = -old_theta pour simplifier – yairchu

+1

hmm, votre ligne de carte se plaint de dimensi ons. J'ai dû réécrire comme x [: 2] = array ([xline.split ("") [1: 3]], dtype = float) .transpose() Même chose sur la ligne math.exp je pense que vous avez besoin de theta .transpose() – MercerKernel

0

Vous pourriez utiliser la déclaration with.

+1

sauf que personne n'obtient * l'instruction with ... –

+1

-1: de quelle façon? Juste au hasard? ou avec quelque chose en tant que but? –

+0

pour la gestion des fichiers. – Geo

9

Un changement évident est de se débarrasser de la "for i in range (1, 100):" et de simplement itérer sur les lignes de fichier. Pour itérer sur les deux fichiers (xfile et yfile), compressez-les. à-dire remplacer ce bloc avec quelque chose comme:

import itertools 

for xline, yline in itertools.izip(xfile, yfile): 
    s= xline.split(" ") 
    x[0] = float(s[1]) 
    x[1] = float(s[2]) 
    y = float(yline) 
    ... 

(Cela suppose le fichier est de 100 lignes, (vous voulez que le fichier entier) Si vous restreindre délibérément les premières 100 lignes, vous.. pourrait utiliser quelque chose comme:.

for i, xline, yline in itertools.izip(range(100), xfile, yfile): 

Cependant, son mauvais rendement à itérer sur le même fichier 6 fois - mieux pour le charger en mémoire à l'avance, et la boucle au-dessus de là, soit en dehors de votre boucle, ont:

xfile = open("q1x.dat", "r") 
yfile = open("q1y.dat", "r") 
data = zip([line.split(" ")[1:3] for line in xfile], map(float, yfile)) 

Et à l'intérieur juste:

for (x1,x2), y in data: 
    x[0] = x1 
    x[1] = x2 
    ... 
+1

qui devrait être line.split ("") [1: 3] comme yairchu l'a fait. Diviser deux espaces, ce site édite mon code. – MercerKernel

+0

Oops, vous avez raison - j'ai raté ça. Actualisé. – Brian

0

le code qui lit les fichiers dans les listes pourraient être considérablement plus simple

for line in open("q1x.dat", "r"): 
    x = map(float,line.split(" ")[1:]) 
y = map(float, open("q1y.dat", "r").readlines()) 
+0

vous passez outre x tout le temps. peut-être que vous vouliez x = [map (float, line.split ("") [1:] pour line in open ("q1x.dat", "r") ?? – yairchu

+0

wait son code ne fait-il pas ça aussi? – Nathan

+0

@Nathan: pour effacer une certaine confusion - appelons votre "y" "ys" car il a une liste de tous les "y" dans le code de OP, votre "x" ne peut cependant pas être renommé en "xs" car il a le mêmes valeurs de son "x", alors il semblerait étrange que vous calculiez "x" et "ys" et non "xs" et "ys" J'espère que je suis clair .. – yairchu

3

les matrices gardé arrondissement des nombres entiers jusqu'à ce que j'initialisés une valeur à 0,0. Y a-t-il un meilleur moyen?

En haut de votre code:

from __future__ import division 

En Python 2.6 et versions antérieures, la division entière retourne toujours un entier moins qu'il y ait au moins un nombre à virgule flottante à l'intérieur. En Python 3.0 (et en future division en 2.6), la division fonctionne plus comment nous les humains pourraient s'y attendre.

Si vous voulez division entière pour retourner un entier, et que vous avez importé de futur, utilisez un double //. C'est

from __future__ import division 
print 1//2 # prints 0 
print 5//2 # prints 2 
print 1/2 # prints 0.5 
print 5/2 # prints 2.5 
Questions connexes