Domanda

Potreste dirmi come posso rendere più pitone il seguente codice?

Il codice è corretto. Informativa completa - è il problema 1b nella Handout n. 4 del questo corso di apprendimento automatico. Dovrei usare l'algoritmo di Newton sui due set di dati per adattare un'ipotesi logistica. Ma usano matlab & amp; Sto usando Scipy

Ad esempio, una domanda che ho è che le matrici continuavano ad arrotondare agli interi finché non ho inizializzato un valore su 0,0. C'è un modo migliore?

Grazie

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
È stato utile?

Soluzione

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

Altri suggerimenti

Un ovvio cambiamento è quello di sbarazzarsi di " per i nell'intervallo (1, 100): " e basta scorrere le righe del file. Per scorrere su entrambi i file (xfile e yfile), comprimili. cioè sostituisci quel blocco con qualcosa del tipo:

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

(Questo presuppone che il file sia composto da 100 righe (ad es. si desidera l'intero file). Se si sta deliberatamente limitando le prime 100 righe, è possibile utilizzare qualcosa del tipo:

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

Tuttavia, è anche inefficiente iterare sullo stesso file 6 volte - è meglio caricarlo in memoria in anticipo e passarci sopra, ad es. fuori dal tuo ciclo, avere:

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

E dentro solo:

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

le matrici hanno continuato ad arrotondare a numeri interi fino a quando non ho inizializzato un valore   a 0,0. C'è un modo migliore?

Nella parte superiore del codice:

from __future__ import division

In Python 2.6 e precedenti, la divisione intera restituisce sempre un numero intero a meno che non ci sia almeno un numero in virgola mobile all'interno. In Python 3.0 (e nella divisione futura nella 2.6), la divisione funziona più di come noi umani potremmo aspettarci.

Se desideri la divisione di numeri interi per restituire un numero intero e hai importato da futuro , usa un doppio //. Questo è

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

Puoi utilizzare con statement.

il codice che legge i file negli elenchi potrebbe essere drasticamente più semplice

for line in open("q1x.dat", "r"):
    x = map(float,line.split("  ")[1:])
y = map(float, open("q1y.dat", "r").readlines())
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top