首页 > 解决方案 > Pythonic 线性回归

问题描述

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

有没有更漂亮或 Pythonic 的方式来写这个?

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  

感谢您的任何意见。

标签: pythonpython-2.7numpylinear-regression

解决方案


  1. 这个问题属于代码审查而不是堆栈溢出。

  2. 使用评论来解释为什么不是什么。您的代码应该足够清晰,以至于它所做的事情不需要注释。但有时(不是在这种情况下),你需要一个评论来解释你为什么做了一些不明显的事情。

  3. 带有 numpy 的循环和列表推导可以被认为是代码异味。首先,寻找内置函数,然后尝试找到矢量化方法。如果做不到这一点,您可能需要求助于循环/列表理解,但通常情况并非如此。例如,在这种情况下,numpy 带有np.random.randint.

  4. 使用变量而不是将常量值传递给函数,特别是如果您使用它们两次!你想要1000你的xy数组中的值,把它放在一个变量中。

  5. 每次调用时,您的代码都会重新拟合回归regress,这在计算上是浪费的。看看interp1dscipy 中的工作方式。它的输出是一个可以重复用于插值的函数。在您的情况下,这也是一个很好的模式,您可以使用函数式编程中称为闭包的概念来实现它。这将更容易在代码中解释:

    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 的支持。不要学习使用已经过时的语言!

推荐阅读