如何使这段代码更具Python风格?

3 投票
5 回答
787 浏览
提问于 2025-04-15 12:18

你们能告诉我怎么让以下代码更符合Python的风格吗?

这段代码是对的。坦白说,这是斯坦福大学机器学习课程的第4份讲义中的问题1b。我的任务是用牛顿算法对两个数据集进行逻辑假设的拟合。不过他们用的是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 个回答

3

这些矩阵一直四舍五入到整数,直到我把一个值初始化为0.0。有没有更好的方法呢?

在你的代码顶部:

from __future__ import division

在Python 2.6及更早版本中,整数相除总是返回整数,除非其中至少有一个是浮点数。在Python 3.0(以及2.6中的未来除法)中,除法的结果更符合我们人类的直觉。

如果你想让整数相除返回整数,并且你已经从未来导入了相关功能,那么可以使用双斜杠//。也就是说:

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
9

一个明显的改动是去掉“for i in range(1, 100):”这部分,直接遍历文件的每一行。要同时遍历两个文件(xfile 和 yfile),可以使用 zip 函数。也就是说,把那段代码替换成类似下面的内容:

 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

当然可以!请看下面的内容:

在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要将它们转换成程序可以使用的格式。

比如说,如果我们从一个网页上获取了一些信息,这些信息可能是以文本的形式存在的。我们需要把这些文本解析成程序可以操作的对象,比如数字、列表或者字典。这样一来,我们就可以对这些数据进行计算、排序或者其他操作。

在这个过程中,我们可能会用到一些工具或者库,这些工具可以帮助我们更方便地处理数据。比如说,有些库可以自动将文本转换成我们需要的格式,省去了很多手动操作的麻烦。

总之,处理数据的过程就是将原始信息转化为程序可以理解和使用的形式,这样才能让我们的程序更智能、更高效。

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

撰写回答