Използван модел на линейна регресия

Понастоящем велосипеди под наем се въвеждат в много градски градове за подобряване на комфорта при придвижване. Важно е велосипедът под наем да бъде наличен и достъпен за обществеността в точното време, тъй като това намалява времето за чакане. В крайна сметка осигуряването на града със стабилно предлагане на велосипеди под наем се превръща в основна грижа. Решаващата част е прогнозирането на броя велосипеди, необходими на всеки час за стабилно предлагане на велосипеди под наем.

Описание на данните

Наборът от данни съдържа информация за времето (температура, влажност, скорост на вятъра, видимост, точка на оросяване, слънчева радиация, снеговалеж, валежи), броя велосипеди, наети на час и информация за датата.

Информация за атрибута:

  • Дата: година-месец-ден
  • Брой велосипеди под наем — Брой велосипеди под наем на всеки час.
  • Час — час от деня
  • Температура-Температура в Целзий
  • Влажност — %
  • Скорост на вятъра — m/s
  • Видимост - 10м
  • Температура на точката на оросяване — Целзий
  • Слънчева радиация — MJ/m2
  • Валежи — mm
  • Снеговалеж — см
  • Сезони - Зима, Пролет, Лято, Есен
  • Празник — Празник/Без празник
  • Функционален ден — NoFunc (нефункционални часове), Fun (функционални часове)

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.

Блок-схема на проекта:

  1. Зареждане на данни и диагностика на данните
  2. Филтриране на данни
  3. EDA на редови данни за разбиране на вътрешни корелации.
  4. Инженеринг на характеристиките
  5. Избор на функция: не използваме много поради ограничените функции в нашите данни (само една функция елиминира използването на Hitman за ескалиране на проблема с мултиколинеарността)
  6. Моделна сграда
  7. Обучение и тестване на модели
  8. Оценка на модела и настройка на хипер параметри.
  9. Внедряване на модела

1. Импортирайте библиотеки и данни

опитайте се да решите с първата линейна регресия.

# Import necessary libraries
import pandas as pd     #provides wide variety tools for data analysis,many inbuilt methods for grouping, combining and filtering data.
import numpy as np      #for some basic mathematical operations
from matplotlib import pyplot as plt #comprehensive library for creating static, animated, and interactive visualizations
import seaborn as sns                #  high-level interface for drawing attractive and informative statistical graphics
from sklearn.model_selection import train_test_split, GridSearchCV,  cross_val_score
from sklearn import preprocessing, linear_model
from sklearn.preprocessing import  LabelEncoder,OneHotEncoder
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler 
from sklearn.metrics import r2_score, mean_squared_error, accuracy_score
from  sklearn.linear_model import LinearRegression
import warnings
warnings.filterwarnings('ignore')
pd.pandas.set_option('display.max_columns',None)
%matplotlib inline

1.1 _ Зареждане на данни

Вече можем да създадем рамка с данни на Pandas, използвайки изтегления файл, за да преглеждаме и анализираме данните.

In [2]:

# Read the csv file
data=pd.read_csv('SeoulBikeData.csv',encoding= 'unicode_escape')

1.1.1 _ Данни за първи поглед и идентифициране на функции

Наборът от данни съдържа 8760 реда и 14 колони. Всеки ред от набора от данни съдържа информация за метеорологичните условия.

Нашата цел е да намерим начин да оценим прогнозната стойност на броя велосипеди, необходими на всеки час за стабилно предлагане на велосипеди под наем. използвайки стойностите в другите колони. Ако можем да направим това за историческите данни, тогава би трябвало да сме в състояние да оценим необходимия брой велосипеди на всеки час.

1.1.2 _Първа проверка на дублиращите се записи в данните

  • Дублиращите се записи дават грешна прогноза и също така консумират ненужно съхранение и отнемат време по време на тестване и данни за обучение.
# Check for duplicated entries.
print("Duplicate entry in data:",len(data[data.duplicated()]))
Duplicate entry in data: 0

Не са намерени дублирани записи в данните

1.2 _ Диагностициране на данните

# Custom Function for Dtype,Unique values and Null values
def datainfo():
    temp_ps = pd.DataFrame(index=data.columns)
    temp_ps['DataType'] = data.dtypes
    temp_ps["Non-null_Values"] = data.count()
    temp_ps['Unique_Values'] = data.nunique()
    temp_ps['NaN_Values'] = data.isnull().sum()
    temp_ps['NaN_Values_Percentage'] = (temp_ps['NaN_Values']/len(data))*100 
    return temp_ps
# Shape of the data.
print("Total Rows and Columns in DataFrame is :",data.shape,"\n") 
# Custom Function
datainfo()
Total Rows and Columns in DataFrame is : (8760, 14)

Намиране на подробности от данни:

  • Има 14 функции с 8760 реда данни.
  • Има 3 категориални колони и 11 цифрови колони. Колоните „Дата“, „Сезони“ и „Функционален ден“ са от тип данни 𝑜𝑏𝑗𝑒𝑐𝑡
  • Колоните „Брой велосипеди под наем“, „Час“, „Влажност (%)“ и „Видимост (10𝑚)“ са от 𝑖𝑛𝑡64 цифров тип данни
  • Колони „Температура (℃)“, „Скорост на вятъра (𝑚/𝑠)“, „Температура на точката на оросяване (℃)“, „Слънчева радиация (𝑀𝐽/𝑚2)“, „Валеж (𝑚𝑚)“ и „Снеговалеж (𝑐𝑚) са от 𝑓𝑙𝑜𝑎𝑡64 цифров тип данни
  • Нито една нулева стойност не присъства в нито една колона
  • Уникален брой: Сезони - 4, Празници - 2, Работен ден - 2
# Statistical info.
data.describe().T   #.T use for transpose the describe table

Диапазоните от стойности в цифровите колони също изглеждат разумни, така че може да не се налага да почистваме много данни. Колоната „Скорост на вятъра“, „Температура на точката на оросяване (°C)“, „Слънчева радиация“, „Валеж“ и „Снеговалеж“ обаче изглежда значително изкривена, тъй като медианата (50 персентил) е много по-ниска от максималната стойност .

2. Филтриране на данни

2.1_Филтриране на дните на велосипед под наем

#for chech functioning and non functioning day ,plot (Hour Vs Rented Bike Count Graph)
def barplots(x,y,hue):
    plt.figure(figsize=(15,7))
    sns.set_palette("husl")
    sns.barplot(x=x,y=y,hue=hue,data=data);
barplots('Hour','Rented Bike Count','Functioning Day')

# Grouping by functioning day and calculating the total Rented Bike Count
data.groupby('Functioning Day').sum()['Rented Bike Count'].sort_values(ascending = False).reset_index()

Според диагностичните данни е установено, че велосипедът под наем се дава само в работния ден, така че премахнете неработещите дни и след това премахнете колоната за работещ ден Als

#Removing data of non functional days (non rented days)
df=data.drop(data[data['Functioning Day'] == 'No'].index)
#Due to not unsefull in Functioning Day Column ,remove Functioning Day Column
df1=df.drop(['Functioning Day'], axis = 1
#Checking DataFrame Shape After Removing Non Functional Day Rows And Functional Day Column
print("Filtered Dataframe with only rented bike days :",df1.shape,"\n")
Filtered Dataframe with only rented bike days : (8465, 13)

2.2 _ Отделете колона за дата, месец, година от дата

Първо, нека преобразуваме Date в date column и да извлечем различни части от датата.

#convert in datetime64[ns] datatype
df1['Date'] = pd.to_datetime(df1['Date']) 
df1['Date']
0      2017-01-12
1      2017-01-12
2      2017-01-12
3      2017-01-12
4      2017-01-12
          ...    
8755   2018-11-30
8756   2018-11-30
8757   2018-11-30
8758   2018-11-30
8759   2018-11-30
Name: Date, Length: 8465, dtype: datetime64[ns]
#Seperate Day, Month, Year from DataFrame Column
df1['Day']=df1['Date'].dt.day
df1['Month']=df1['Date'].dt.month
df1['Year']=df1['Date'].dt.year

In [14]:

# drop the Date column after extracting necessory information
df1.drop(columns=['Date'],inplace=True)

3. Проучвателен анализ и визуализация Нека изследваме данните, като визуализираме разпределението на стойностите в някои колони от набора от данни и връзките между „Брой велосипеди под наем“ и други колони.

Ще използваме библиотеките Matplotlib, Seaborn за визуализация.

3.1 _ Проверка на корелацията на данните

Корелацията е статистическа мярка, която изразява силата на връзката между две променливи.

Двата основни типа корелация: положителна и отрицателна.

Положителна корелация възниква, когато две променливи се движат в една и съща посока; както едното се увеличава, така и другото.

Отрицателна корелация възниква, когато две променливи се движат в противоположни посоки; като едното нараства, другото намалява.

Корелацията може да се използва за тестване на хипотези за причинно-следствени връзки между променливи. Корелацията често се използва в реалния свят за прогнозиране на тенденции.

#.corr() use to find correlation with data
data_corr= df1.corr()       
plt.figure(figsize=(12,12))
#cmap use for colour palette , linewidths : set the width of the lines that divide the cells, 
#annot :helps in annotating the heatmap with values if set to True, otherwise values are not provided , linecolor : helps in setting the color of each line that divides heatmap cells
sns.heatmap(data_corr, cmap='coolwarm', linewidths=0.1, annot=True, linecolor='white')

temperature и Dew point temperature са почти 0,91 корелирани, така че е генериран проблем с мултиколинеарност. така че изпускаме функцията Dew point temperature, защото ако видим, че Dew point temperature е почти 0,4 свързано с нашата целева променлива, която е по-малка от temperature 0,56.

#Drop Dew point temperature(°C) from dataset df1
df1.drop(columns=['Dew point temperature(°C)'],inplace=True)

Намиране на вътрешности:

  • Можем да видим, че с нашата целева променлива (брой велосипеди под наем) най-корелираните променливи са час, температура, температура на точката на оросяване

3.2 _ Отделни числови и категорични променливи

Категоричните данни са тип данни, които се използват за групиране на информация с подобни характеристики.

Числовите данни са тип данни, които изразяват информация под формата на числа.

Числени променливи

#if dtype is not Equal to object type then its a num data
numerical_features=df1.columns[df1.dtypes!='object'].tolist()
numerical_features
['Rented Bike Count',
 'Hour',
 'Temperature(°C)',
 'Humidity(%)',
 'Wind speed (m/s)',
 'Visibility (10m)',
 'Solar Radiation (MJ/m2)',
 'Rainfall(mm)',
 'Snowfall (cm)',
 'Day',
 'Month',
 'Year']

In [18]:

# Seprate dataframe for Numerical feature
num_data=df1[numerical_features]
num_data

#plot num data to analysis data distribution
fig = plt.figure(figsize = (20,5))
for index,column in enumerate(numerical_features) :
  plt.subplot(3,5,index+1)
  sns.distplot(df1[column])
  feature = df1[column]
  ax = fig.gca() # get current axes
  ax.axvline(feature.mean(), color='#ff033e', linestyle='dashed', linewidth=2)  #Rose-Red Color indicate mean of data
  ax.axvline(feature.median(), color='#00ffff', linestyle='dashed', linewidth=2) #Cyan indicate median of data
  plt.title(f'{column.title()}')
  plt.tight_layout()

df1.agg(['skew', 'kurtosis']).transpose()

Дясно/положително изкривено разпределение: Режим ‹ Медиана ‹ Средно: Брой велосипеди под наем, скорост на вятъра (m/s), слънчева радиация (MJ/m2)

Без изкривяване: Средно = Медиана = Режим: Час, Температура, Влажност (%), Валеж (mm), Снеговалеж (cm)

Ляво/отрицателно изкривено разпределение: средно ‹ медиана ‹ режим: видимост (10 м)

Ляво изкривено разпределение:

  • Средната стойност обикновено е по-малка от медианата, а режимът обикновено е по-голям както от средната, така и от медианата.
  • По-голямата част от данните са концентрирани в дясната страна на разпределението, с няколко екстремни стойности в лявата опашка.
  • Разпределението може да има дълга опашка от лявата страна, което показва, че има някои екстремни стойности, които са много по-ниски от по-голямата част от данните.
  • Изкривеното ляво разпределение може да бъде причинено от наличието на отклонения с ниски стойности.
  • Лявото изкривено разпределение може да повлияе на статистическите анализи, които приемат n нормалност и може да изисква трансформиране на данните преди провеждането на определени анализи.

Дясно изкривено разпределение:

  • Средната стойност обикновено е по-голяма от медианата, а режимът обикновено е по-малък както от средната, така и от медианата.
  • По-голямата част от данните са концентрирани в лявата страна на разпределението, с няколко екстремни стойности в дясната опашка.
  • Разпределението може да има дълга опашка от дясната страна, което показва, че има някои екстремни стойности, които са много по-високи от по-голямата част от данните.
  • Дясното изкривено разпределение може да бъде причинено от наличието на извънредни стойности с високи стойности.
  • Дясното изкривено разпределение може да повлияе на статистическите анализи, които приемат нормалност и може да изисква трансформиране на данните преди провеждането на определени анализи.

Дискретни стойности

## Lets analyse the discrete values by creating histograms to understand the distribution
num_discrete_value=[feature for feature in numerical_features if len(df1[feature].unique())<32]
print("Discrete Variables Count: {}".format(len(num_discrete_value)))
fig = plt.figure(figsize = (20,10))
for index,column in enumerate(num_discrete_value) :
  plt.subplot(2,2,index+1)
  dataset=df1.copy()
  dataset.groupby(feature)['Rented Bike Count'].sum().plot(kind='bar',color="#ff033e") #kind=bar use for ploting barchart
  feature = df1[column]
  ax = fig.gca()
  plt.ylabel('Total Rented Bike Count')
  plt.tight_layout()
  plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.2)
  for p in ax.patches:
      ax.annotate(round(p.get_height()),(p.get_x() + p.get_width()/2,p.get_height()),ha='center',size= 12, rotation=90) #ha use to write count in center and rotation use to rotate count to 90 degree and make clear visible on graph
Discrete Variables Count: 4

Категорични променливи

#For categorical Data
categorical_features=[col for col in df1.columns if df1[col].dtype=='O']
categorical_features

Извън[22]:

['Seasons', 'Holiday']

In [23]:

# Seprate dataframe for Categorical feature
cat_data=df1[categorical_features]

In [24]:

# Unique number of categorical features
for feature in categorical_features:
    print('The feature is {} and number of categories are {}'.format(feature,len(data[feature].unique())))
The feature is Seasons and number of categories are 4
The feature is Holiday and number of categories are 2

In [25]:

# GROUPING BY SEASONS AND CALCULATING THE TOTAL RENTED BIKE COUNT
data.groupby('Seasons').sum()['Rented Bike Count'].sort_values(ascending = False).reset_index()

Извън[25]:

In [26]:

# GROUPING BY HOLIDAY AND CALCULATING THE TOTAL RENTED BIKE COUNT
data.groupby('Holiday').sum()['Rented Bike Count'].sort_values(ascending = False).reset_index()

Извън[26]:

Ваканция — — Брой велосипеди под наем0

Без празник — -› 59564191

Празник — — -›215895

Категорични стойности

In [27]:

#Find out the relationship between categorical variable and dependent feature Rented Bike Count
fig = plt.figure(figsize = (20,10))
for index,column in enumerate(categorical_features) :
    plt.subplot(1,2,index+1)
    dataset=df1.copy()
    dataset.groupby(feature)['Rented Bike Count'].sum().plot(kind='bar',color="#ff033e")
    feature = df1[column]
    ax = fig.gca()
    plt.ylabel('Total Rented Bike Count')
    plt.tight_layout()
    plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.2)
    for p in ax.patches:
        ax.annotate(round(p.get_height()),(p.get_x() + p.get_width()/2,p.get_height()),ha='center',size= 12, rotation=90)

In [28]:

fig, axs = plt.subplots(nrows=2,ncols=1,figsize=(15,8), dpi=100)
sns.pointplot(data=dataset, x="Hour", y="Rented Bike Count", ax=axs[0], 
              hue="Holiday")
sns.lineplot(data=dataset, x="Hour", y="Rented Bike Count", ax=axs[1], 
              hue="Seasons", marker="x",markeredgecolor="black")
plt.tight_layout()

Точковата диаграма е вид статистическа визуализация, която показва средната стойност и доверителния интервал (или ленти за грешка) на числова променлива за различни категории или групи. В точков график средната стойност е представена от точка или маркер, а лентите за грешки показват доверителния интервал или стандартната грешка на средната стойност. Това е особено полезно за сравняване на средните стойности на различни групи или категории в набор от данни.

  • Погледнете лентите за грешки, за да определите доверителния интервал или стандартната грешка на средната стойност. Дължината на лентите на грешката показва диапазона от стойности, в рамките на който е вероятно да попадне истинската средна стойност на съвкупността с дадено ниво на достоверност.

4. Инженеринг на функции върху данни

  • Кодиране на категорични данни в единични вектори.
  • Идентифицирайте входовете и целта
  • Мащаб на стойности в цифрови колони до диапазон (0,1)(0,1).
  • Разделете набора от данни на набори за обучение и валидиране.

4.1 _ Кодиране на данни

Кодиране на категорични данни в двата енкодера и проверка на точността на енкодерите:

  • oh_df : Данни на OneHotEncoder
  • le_df : Данни на LabelEncoder

4.1.1 _ Прилагане на OneHotEncoder върху данни

Тъй като моделите за машинно обучение могат да се обучават само с числови данни, трябва да преобразуваме категоричните данни в числа. Често срещана техника е да се използва еднократно кодиране за категориални колони.

Едно горещо кодиране включва добавяне на нова двоична (0/1) колона за всяка уникална категория на категорична колона.

In [29]:

oh_df=pd.get_dummies(df1, columns=['Seasons', 'Holiday'], drop_first=True)
oh_df

Подходът за еднократно кодиране елиминира реда, но води до значително разширяване на броя на колоните. Така че за колони с повече уникални стойности опитайте да използвате други техники като кодиране на етикет

4.1.2 _ Прилагане на енкодер на етикети

In [30]:

# Encode labels of multiple columns at ones using LabelEncoder
le_df=pd.get_dummies(df1,columns=['Holiday','Seasons','Functioning Day','Hour'],drop_first=True)

Проверка на данните в колоната за сезон

In [31]:

df1.groupby("Seasons").count()  #for checking raw data

Извън[31]:

In [32]:

le_df.groupby('Seasons').count() #Seasons convert to numerical after apply transformation on data

Извън [32]:

0: Есен, 1: Пролет, 2: Лято, 3: Зима Забележете, че 0,1,2,3 е просто начинът на представяне. Не съдържа никакъв вид доминиране или въздействие

Проверка на разпределението и контура на рамката с данни

#checking for outliers
plt.figure(figsize=(10,5))   # for define chart size
plt.xticks(rotation =90)     #plot X-axis ticks in 90 degree rotation for clear visible
sns.boxplot(data = le_df)    #box plot of le_df data frame raw data
plt.show()

Анализ на разпределението на целевия параметър Rented Bike Count...

plt.figure(figsize=(10,5))
plt.boxplot(le_df['Rented Bike Count'],vert=False)
plt.show()

Откриване на очертания чрез интерквартилен диапазон

Квадратен корен — — -›Методът на квадратен корен обикновено се използва, когато данните ви са умерено изкривени. Сега използването на корен квадратен (напр. sqrt(x)) е трансформация, която има умерен ефект върху формата на разпределението. Обикновено се използва за намаляване на изкривените надясно данни. И накрая, квадратният корен може да се приложи към нулеви стойности и най-често се използва при преброени данни.

Трансформация на квадратен корен: Преобразувайте стойностите от y в √y.

Регистрационна трансформация Логаритмичната е силна трансформация, която има голям ефект върху формата на разпределението. Тази техника, подобно на метода на квадратния корен, често се използва за намаляване на дясното изкривяване. Заслужава да се отбележи обаче, че не може да се прилага към нулеви или отрицателни стойности.

Регистрационна трансформация: Преобразувайте стойностите от y в log(y).

Трансформацията на кубичен корен включва преобразуване на x в x^ (1/3). Това е доста силна трансформация със съществен ефект върху формата на разпределението: но е по-слаба от логаритъма. Може да се прилага и за отрицателни и нулеви стойности. Отрицателно изкривени данни

Трансформация на кубичен корен: Преобразувайте стойностите от y в y^(1/3).

#apply diffrent tranformation technique and checking data distributation
fig,axes = plt.subplots(1,4,figsize=(20,5))
sns.distplot((le_df['Rented Bike Count']),ax=axes[0],color='brown').set_title(" Input data")
sns.distplot(np.log1p(le_df['Rented Bike Count']+0.0000001),ax=axes[1],color='red').set_title("log1p") #transform only posible in positive value and >0 value so add 0.0000001 in data
sns.distplot(np.sqrt(le_df['Rented Bike Count']),ax=axes[2], color='blue').set_title("Square root")
sns.distplot(np.cbrt(le_df['Rented Bike Count']*2),ax=axes[3], color='green').set_title("cube root")
Text(0.5, 1.0, 'cube root')
import scipy.stats as stats
def plotvariable(df,variable):
  plt.figure(figsize=(10,5))
  plt.subplot(1,2,1)   #means 1 row, 2 Columns and 1st plot
  df[variable].hist(bins=30)
  ##QQ plot
  plt.subplot(1,2,2)
  stats.probplot(df[variable], dist='norm',plot=plt)
  plt.show()
  print(df[variable].skew())
plotvariable(le_df,'Rented Bike Count')

0.7938148420670103

нашата Rented Bike Count цел не е нормално разпределена, така че трябва да направим някои трансформации преди доставка към модела

data["RBC_qb"]=np.cbrt(data['Rented Bike Count']) #try cube root technique to convert positive screwd to normal distributation
plotvariable(data,"RBC_qb")
data['RBC_qb'].skew()
-0.31775917995579267
-0.31775917995579267
plt.figure(figsize=(10,5))
plt.boxplot(data["RBC_qb"],vert=False)
plt.show()
le_df_=le_df.copy()
le_df_['Rented Bike Count']=np.sqrt(le_df['Rented Bike Count'])
plotvariable(le_df_,'Rented Bike Count')
le_df_['Rented Bike Count'].skew()
0.16925358699257584
0.16925358699257584
plt.figure(figsize=(10,5))
plt.boxplot(le_df_["Rented Bike Count"],vert=False)
plt.show()

Сега изглежда като нормално разпределение

plotvariable(le_df,'Wind speed (m/s)')
0.8616479716535727

не изглежда като нормално и правилно прецакано разпределение, така че трябва да приложите трансформация.

le_df_['Wind speed (m/s)']=np.sqrt(le_df['Wind speed (m/s)'])
plotvariable(le_df_,'Wind speed (m/s)')
-0.014489471518114892

изглежда като нормално разпределение.

Но ние сме със sklearn Power Transformer class

le_df.drop(columns='Year',inplace=True)
var=list(le_df.select_dtypes(include=['float64','int64']).columns)


from sklearn.preprocessing import PowerTransformer
sc_X=PowerTransformer(method = 'yeo-johnson')
le_df[var]=le_df.fit_transform(df1[var])

4.2 _ Идентифициране на входове и цели

  • Колоната Rented Bike Count съдържа стойността, която трябва да предвидим, т.е. това е целевата колона.
  • Данните от всички останали колони (с изключение на първата и последната колона) могат да се използват като входни данни за модела.

Създайте списък X с имена на колони, съдържащи данни, които могат да се използват като входни данни за обучение на модела, и идентифицирайте целевата колона като променлива y.

Уверете се, че колоните Date и Rented Bike Count не са включени.

Сега, след като идентифицирахме входните и целевите колони, можем да разделим входните и целевите данни.

# Identify the input columns (a list of column names)
X=le_df.drop('Rented Bike Count',axis=1)
y=le_df['Rented Bike Count']

4.3 _ Разделяне на комплект за обучение и тестване

Накрая, нека разделим набора от данни на набор за обучение и тестване. Ще използваме произволно избрани 30% подмножество от данните за валидиране. Освен това ще използваме само цифровите и кодираните колони.

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
# Let's check the shape of the train and test dataset
print(f'The shape of the train and test set for the independent variables are : X_train = {X_train.shape}, X_test = {X_test.shape}')
print(f'The shape of the train and test set for the dependent variables are : y_train = {y_train.shape}, y_test = {y_test.shape}')
The shape of the train and test set for the independent variables are : X_train = (6772, 13), X_test = (1693, 13)
The shape of the train and test set for the dependent variables are : y_train = (6772,), y_test = (1693,)

5. Мащабиране на данни и изграждане на модел с помощта на различни регресионни техники

Регресията търси връзки между променливите.

Зависимите характеристики се наричат ​​зависими променливи, резултати или отговори.

Независимите характеристики се наричат ​​независими променливи, входящи данни, регресори или предиктори.

def predict(ml_model,X,y):
    X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.20,random_state=10)
    rob =RobustScaler()
    X_train = rob.fit_transform(X_train)
    X_test = rob.transform(X_test)
    model=ml_model.fit(X_train,y_train)
    y_pred=model.predict(X_test)
    plt.scatter(y_pred,y_test,color='b')
    plt.xlabel('Predicted')
    plt.ylabel('Actual')
    print(f'R^2 is {model.score(X_test,y_test)}\n Adj R^2 is {1-(1-model.score(X_test,y_test))*(len(y_test)-1)/(len(y_test)-X_test.shape[1]-1)}\n RMSE is: {mean_squared_error(y_test,y_pred,squared=False)}')

R2 показва доколко термини (точки от данни) пасват на крива или линия. Коригираният R2 също показва колко добре термините пасват на крива или линия, но се коригира за броя на термините в модела. Ако добавяте повече и повече безполезни променливи към модел, коригираният r-квадрат ще намалява. Ако добавите повече полезни променливи, коригираният r-квадрат ще се увеличи.

Коригираният R2 винаги ще бъде по-малък или равен на R2.

R2 предполага, че всяка отделна променлива обяснява вариацията в зависимата променлива.

Коригираният R2 ви казва процента на вариация, обяснен само от независимите променливи, които действително засягат зависимата променлива.

MSE е рискова функция, която ни позволява да изчислим средната квадратна разлика между прогнозираната и действителната стойност на функция или променлива.

RMSE е съкращение за средна квадратна грешка, което е корен квадратен от стойността, получена от функцията за средна квадратна грешка.

Линейна регресия:

Тук има множество зависими променливи, така че това се нарича множествена линейна регресия.

predict(LinearRegression(),X,y)
R^2 is 0.7841055740368184
 Adj R^2 is 0.781175270450891
 RMSE is: 0.47085002746837