Простая проблема линейной регрессии в Python

#python #time-series #linear-regression

Вопрос:

У меня есть эти данные:

введите описание изображения здесь

и я пытаюсь построить на нем простую модель линейной регрессии.

Вот мой код:

 from sklearn.linear_model import LinearRegression

X = df[['Date']] 
y = df['ACP Cleaning'] 

model = LinearRegression()
model.fit(X, y)

X_predict = [['2021-1-1']]
y_predict = model.predict(X_predict)
 

и в этом моя ошибка:

Ошибка значения: Не удается преобразовать массив байтов/строк в десятичные числа с помощью dtype=’числовой’

Комментарии:

1. Я говорю это с самыми добрыми намерениями: если вы ничего не знаете о простой базовой алгебре, лежащей в основе этой вещи, работа на Python не станет проще. Для начала все переменные в регрессии должны быть числовыми. Вам нужно будет сопоставить эти строки с числами.

Ответ №1:

Линейная регрессия работает с числами, а не со строками.

Вы должны предварительно обработать свои данные, чтобы они соответствовали входным данным модели.

Один из способов сделать это-проанализировать строку и преобразовать ее в метку времени:

 import datetime

def process_date(date_str):
  d = datetime.datetime.strptime(date_str, '%Y-%m-%d')
  return d.timestamp()

X = df[['Date']].apply(process_date)
 

То же самое необходимо сделать с данными, которые вы хотите спрогнозировать.

Обновление: Если тип данных вашего набора данных правильный, то проблема в данных, которые вы пытаетесь использовать для прогнозирования (вы не можете предсказать строку).

Ниже приведен полный рабочий пример. Обратите пристальное внимание на обработку, выполняемую с X_predict переменной.

 import datetime
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression

rng = pd.date_range('2015-02-24', periods=5, freq='3A')
df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))})
print(df.head())

X = np.array(df['Date']).reshape(-1,1)
y = df['Val']

model = LinearRegression()
model.fit(X, y)

def process_date(date_str):
  d = datetime.datetime.strptime(date_str, '%Y-%m-%d')
  # return array
  return [d.timestamp()]


X_predict = ['2021-1-1']
X_predict = list(map(process_date, X_predict))
y_predict = model.predict(X_predict)
y_predict
 

ВОЗВРАТ:

         Date       Val
0 2015-12-31 -0.110503
1 2018-12-31 -0.621394
2 2021-12-31 -1.030068
3 2024-12-31  1.221146
4 2027-12-31 -0.327685

array([-2.6149628])
 

Обновление: Я использовал ваши данные для создания csv-файла:

 Date,Val
1-1-2020, 90404.71
2-1-2020, 69904.71
...
 

А потом я загрузился пандами. Мне все кажется хорошим:

 def process_date(date_str):
  # the date format is month-day-year
  d = datetime.datetime.strptime(date_str, '%m-%d-%Y')
  return d.timestamp()

df = pd.read_csv("test.csv")
df['Date'] = df['Date'].apply(process_date)
df.head()
 

Выход:

 Date    Val
0   1.577848e 09    90404.710
1   1.580526e 09    69904.710
2   1.583032e 09    98934.112
3   1.585710e 09    77084.430
4   1.588302e 09    35877.420
 

Извлечение функций:

 # must reshape 'cause we have only one feature
X = df['Date'].to_numpy().reshape(-1,1)
y = df['Val'].to_numpy()
model = LinearRegression()
model.fit(X, y)
 

Предсказывающий:

 X_predict = ['1-1-2021', '2-1-2021']
X_predict = np.array(list(map(process_date, X_predict)))
X_predict = X_predict.reshape(-1, 1)
y_predict = model.predict(X_predict)
y_predict
 

Выход:

 array([55492.2660361 , 53516.12292932])
 

Это хороший прогноз. Вы можете использовать matplotlib для построения своих данных и убедить себя:

 import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(df['Date'], df['Val'])
plt.show()
 

Комментарии:

1. Я получаю эту ошибку при запуске кода: ошибка типа: strptime() аргумент 1 должен быть str, а не серия

2. @juge Я обновил свой ответ полным примером.

3. Спасибо тебе, Хуан! Это работает.

4. Я изменил свои x и y на столбцы моего фрейма данных, но прогноз выходит слишком большим, он должен быть около 9 тыс., это 1,2 миллиона, это агрегирование? 1.2 может быть цифрой за целый год? @JuanR

5. можете ли вы загрузить свой набор данных куда-нибудь, чтобы я мог взглянуть на него?

Ответ №2:

Линейная регрессия требует, чтобы ваши массивы были числового типа, поскольку у вас есть даты, которые хранятся в виде строк в вашем X массиве, Линейная регрессия не будет работать так, как вы ожидаете.

Вы можете преобразовать X массив в числовой тип, подсчитав количество дней с даты начала. Вы можете попробовать что-то подобное в своем фрейме данных:

 df.Date = (df.Date -  df.Date[0]).days
 

И тогда вы сможете продолжать делать то, что делали.

Я предположил, что даты в вашей Date колонке указаны в datetime формате, иначе вам нужно было бы сначала преобразовать их.