Pregunta

¿Podrían decirme cómo puedo hacer que el siguiente código sea más pitónico?

El código es correcto. Revelación completa: es el problema 1b en el Folleto n. ° 4 de este curso de aprendizaje automático. Se supone que debo usar el algoritmo de newton en los dos conjuntos de datos para ajustar una hipótesis logística. Pero usan matlab & amp; Estoy usando scipy

Por ejemplo, una pregunta que tengo es que las matrices se redondearon a enteros hasta que inicialicé un valor a 0.0. ¿Hay una mejor manera?

Gracias

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
¿Fue útil?

Solución

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

Otros consejos

Un cambio obvio es deshacerse de " para i en el rango (1, 100): " y solo iterar sobre las líneas del archivo. Para iterar sobre ambos archivos (xfile e yfile), comprímalos. es decir, reemplazar ese bloque con algo como:

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

(Esto supone que el archivo tiene 100 líneas (es decir, desea el archivo completo). Si está restringiendo deliberadamente a las primeras 100 líneas, puede usar algo como:

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

Sin embargo, también es ineficiente iterar sobre el mismo archivo 6 veces; es mejor cargarlo en la memoria de antemano y recorrerlo allí, es decir. fuera de su ciclo, tenga:

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

Y adentro solo:

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

las matrices siguieron redondeando a enteros hasta que inicialicé un valor   a 0.0. ¿Hay una mejor manera?

En la parte superior de su código:

from __future__ import division

En Python 2.6 y versiones anteriores, la división de enteros siempre devuelve un entero a menos que haya al menos un número de coma flotante. En Python 3.0 (y en la división futuro en 2.6), la división funciona más de lo que los humanos podríamos esperar.

Si desea que la división de enteros devuelva un entero, y ha importado de futuro , use un doble //. Eso es

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

Puede utilizar con declaración.

el código que lee los archivos en listas podría ser drásticamente más simple

for line in open("q1x.dat", "r"):
    x = map(float,line.split("  ")[1:])
y = map(float, open("q1y.dat", "r").readlines())
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top