Как вы делаете этот код более питоническим? - PullRequest
3 голосов
/ 17 июня 2009

Не могли бы вы, ребята, скажите, пожалуйста, как я могу сделать следующий код более понятным?

Код правильный. Полное раскрытие - проблема 1b в раздаточном материале № 4 этого курса машинного обучения. Я должен использовать алгоритм Ньютона на двух наборах данных для подбора логистической гипотезы. Но они используют matlab, а я использую scipy

Например, у меня есть один вопрос: матрицы продолжают округляться до целых, пока я не инициализирую одно значение 0,0 Есть ли лучший способ?

Спасибо

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

Ответы [ 5 ]

9 голосов
/ 17 июня 2009

Одно очевидное изменение - избавиться от «for i in range (1, 100):» и просто перебрать строки файла. Чтобы перебрать оба файла (xfile и yfile), заархивируйте их. т.е. заменить этот блок на что-то вроде:

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

(Предполагается, что файл состоит из 100 строк (т.е. вам нужен весь файл). Если вы намеренно ограничиваетесь первыми 100 строками, вы можете использовать что-то вроде:

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

Однако также неэффективно перебирать один и тот же файл 6 раз - лучше заранее загрузить его в память и выполнить там цикл, т.е. вне вашей петли есть:

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

А внутри всего:

for (x1,x2), y in data:
    x[0] = x1
    x[1] = x2
     ...
4 голосов
/ 17 июня 2009
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
3 голосов
/ 17 июня 2009

матрицы продолжали округляться до целых чисел, пока я не инициализировал одно значение до 0,0. Есть ли лучший способ?

Вверху вашего кода:

from __future__ import division

В Python 2.6 и более ранних версиях целочисленное деление всегда возвращает целое число, если в нем нет хотя бы одного числа с плавающей запятой. В Python 3.0 (и в будущем делении в 2.6) деление работает больше, чем мы, люди, можем ожидать.

Если вы хотите, чтобы целочисленное деление возвращало целое число, и вы импортировали из future , используйте двойной //. Это

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
0 голосов
/ 17 июня 2009

код, который читает файлы в списки, может быть значительно проще

for line in open("q1x.dat", "r"):
    x = map(float,line.split("  ")[1:])
y = map(float, open("q1y.dat", "r").readlines())
0 голосов
/ 17 июня 2009

Вы можете использовать оператор с .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...