Питоническая линейная регрессия - PullRequest
0 голосов
/ 20 мая 2019

Я нарисовал простой кусок кода линейной регрессии.

Будет ли более красивый или питонский способ написать это?

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 Ответ

1 голос
/ 20 мая 2019
  1. Этот вопрос относится к проверке кода , а не к переполнению стека.

  2. Используйте комментарии, чтобы объяснить, почему не что. Ваш код должен быть достаточно понятным, чтобы то, что он делает, не требовало комментариев. Но иногда (не в этом случае) вам понадобится комментарий, чтобы объяснить, почему вы сделали что-то неочевидное.

  3. Циклы и списки с numpy можно считать запахом кода . Сначала ищите встроенные функции, затем попытайтесь найти векторизованный подход. В противном случае вам, возможно, придется прибегнуть к пониманию цикла / списка, но в целом этого не произойдет. например, в этом случае numpy идет с np.random.randint.

  4. Используйте переменные вместо передачи значений констант в функцию, особенно если вы используете их дважды! Вы хотите 1000 значения в ваших x и y массивах, поместите это в переменную.

  5. Ваш код будет соответствовать регрессии каждый раз, когда вы вызываете regress, что приводит к расточительным вычислениям. Посмотрите, как interp1d работает в 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. Наконец, и это действительно важно, нет ничего питонического в использовании 2.7 в 2019 году. Переключение на python 3. Поддержка прекращается на 2 в следующем году. Некоторые крупные библиотеки, такие как pandas, уже отказались от поддержки 2. Не учитесь использовать язык, который уже устарел!
...