Frage

Könnten Sie Kerle mir bitte sagen, wie ich den folgenden Code mehr pythonic machen kann?

Der Code ist korrekt. Vollständige Offenlegung - es ist Problem 1b in Handout # 4 von dieser Maschine Learning-Kurs. Ich soll Algorithmus verwenden Newtons auf den beiden Datensätzen für eine logistische Hypothese passt. Aber sie verwenden Matlab & Ich bin mit scipy

Zum Beispiel eine Frage, die ich habe, ist die Matrizes Rundung auf ganze Zahlen gehalten, bis ich einen Wert auf 0,0 initialisiert. Gibt es einen besseren Weg?

Danke

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
War es hilfreich?

Lösung

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

Andere Tipps

Eine offensichtliche Änderung ist die loszuwerden „for i in range (1, 100):“ und iterieren einfach die Datei Zeilen. Um beiden Dateien iterieren (xfile und yfile), RV sie. dh ersetzt diesen Block mit so etwas wie:

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

(Dies setzt voraus, wird die Datei 100 Zeilen (dh Sie die gesamte Datei wollen) Wenn Sie bewusst sind Beschränkung auf die zuerst 100 Zeilen, Sie so etwas wie verwenden:..

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

Doch es ist auch ineffizient die gleiche Datei 6mal iterieren - besser ist es in dem Speicher im Voraus zu laden, und eine Schleife über es dort, das heißt. außerhalb der Schleife haben:

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

Und innerhalb nur:

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

die Matrizen gehalten auf ganze Zahlen gerundet, bis ich einen Wert initialisiert   0.0. Gibt es einen besseren Weg?

An der Spitze des Codes:

from __future__ import division

In Python 2.6 und früher ganzzahlige Division gibt immer eine ganze Zahl, es sei denn es ist mindestens eine Gleitkommazahl innerhalb. In Python 3.0 (und in Zukunft Aufteilung in 2.6), arbeitet Abteilung mehr, wie wir Menschen erwarten es.

Wenn Sie wollen Integer-Division eine ganze Zahl zurück, und Sie haben importiert von Zukunft , ein Doppel // verwenden. Das ist

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

Sie könnten die Verwendung der mit Aussage.

Sie den Code ein, der die Dateien in Listen liest könnte drastisch einfacher sein

for line in open("q1x.dat", "r"):
    x = map(float,line.split("  ")[1:])
y = map(float, open("q1y.dat", "r").readlines())
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top