我已经编写了一个简单的线性回归代码。
会不会有更漂亮或更Python化的方式写出来?
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from scipy import stats
from random import randint
import numpy as np
def regress(y, x):
reg = slope,intercept,r_value,p_value,std_err = stats.linregress(x,y) ## generate regression elements
yhat = x*reg.slope + intercept ## predict y using with slope(coefficient) and intercept
if __name__=="__main__":
x= np.array([randint(0,1000) for n in range(0,100)]) ## generate 100 random integers between 1 and 1000 for x
y= np.array([randint(0,1000) for n in range(0,100)]) ## generate 100 random integers between 1 and 1000 for y
regress(y,x) ## run function using the 100 random integers for x & y
感谢您的输入。
答案 0 :(得分:1)
此问题属于code review,而不是堆栈溢出。
使用注释解释为什么不这样做。您的代码应该足够清楚,它所做的不需要注释。但是有时候(在这种情况下不是),您需要添加注释以解释为什么做了不明显的事情。
具有numpy的循环和列表推导可以视为code smell。首先,寻找内置函数,然后尝试寻找一种vectorized方法。失败的话,您可能需要求助于循环/列表理解,但通常情况并非如此。例如,在这种情况下,numpy随附np.random.randint
。
使用变量而不是将常量值传递给函数,尤其是如果您两次使用它们!您希望将1000
和x
数组中的y
值放在一个变量中。
每次调用regress
时,您的代码都会重新拟合回归,这在计算上是浪费的。看一下interp1d
works in scipy的方式。它的输出是可以重新用于插值的函数。在您的情况下,这也是一个很好的模式,您可以使用函数编程中的一个closure概念来实现它。这将在代码中更容易解释:
def regress(x, y):
"""
A docstring is more pythonic than unneeded inline comments: https://www.python.org/dev/peps/pep-0257/
"""
slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
def regression_function(xi): # This bit is the closure. Notice how it has access to the variables that are in the parent functions scope. The closure will remember the state of those values even after they go out of scope with the parent function.
return xi*slope + intercept
return regression_function # Return the actual function you created above itself so that you can reuse it later.
并使用它:
n = 1000
data_min = 0
data_max = 100
x = np.random.randint(data_min, data_max, (0,n))
y = np.random.randint(data_min, data_max, (0,n))
f_reg = regress(x,y)
xi = np.arange(1000)
yi = f_reg(xi)
另一种选择是使用scikit-learn。 scikit-learn而不是闭包,而是使用面向对象的方法来记住状态。在这种情况下,您需要先调用fit
方法来学习状态,然后再使用predict
方法来重新使用该学习状态。