Pythonic线性回归

时间:2019-05-19 22:33:08

标签: python python-2.7 numpy linear-regression

我已经编写了一个简单的线性回归代码。

会不会有更漂亮或更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  

感谢您的输入。

1 个答案:

答案 0 :(得分:1)

  1. 此问题属于code review,而不是堆栈溢出。

  2. 使用注释解释为什么不这样做。您的代码应该足够清楚,它所做的不需要注释。但是有时候(在这种情况下不是),您需要添加注释以解释为什么做了不明显的事情。

  3. 具有numpy的循环和列表推导可以视为code smell。首先,寻找内置函数,然后尝试寻找一种vectorized方法。失败的话,您可能需要求助于循环/列表理解,但通常情况并非如此。例如,在这种情况下,numpy随附np.random.randint

  4. 使用变量而不是将常量值传递给函数,尤其是如果您两次使用它们!您希望将1000x数组中的y值放在一个变量中。

  5. 每次调用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)
    
  6. 另一种选择是使用scikit-learn。 scikit-learn而不是闭包,而是使用面向对象的方法来记住状态。在这种情况下,您需要先调用fit方法来学习状态,然后再使用predict方法来重新使用该学习状态。

  7. 最后,这真的很重要,在2019年使用2.7并没有什么pythonic。切换到python 3。明年将取消对2的支持。一些主要的图书馆,例如pandas,已经放弃了对2的支持。不要学习使用已经过时的语言!