このコードをどのようにもっとpythonicにするのですか?
-
06-07-2019 - |
質問
次のコードをもっとPythonicにする方法を教えてください。
コードは正しいです。完全な開示-この機械学習コースの配布資料4の問題1bです。ロジスティック仮説をあてはめるために、2つのデータセットでニュートンのアルゴリズムを使用することになっています。しかし、彼らはmatlab&を使用します。私はscipyを使用しています
たとえば、1つの質問は、1つの値を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
解決
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つは、" 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行であると仮定しています(つまり、ファイル全体が必要です)。意図的に first 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
...
1つの値を初期化するまで、行列は整数に丸め続けられました 0.0に。より良い方法はありますか?
コードの先頭:
from __future__ import division
Python 2.6以前では、整数除算は、少なくとも1つの浮動小数点数が含まれていない限り、常に整数を返します。 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
ファイルをリストに読み込むコードは大幅に単純化できます
for line in open("q1x.dat", "r"):
x = map(float,line.split(" ")[1:])
y = map(float, open("q1y.dat", "r").readlines())