Продолжаем знакомство с Линейной регрессией.
В данной статье мы рассмотрим, как оценить степень точности построенной модели и влияние флуктуаций на точность модели.
Рассмотрение будет производиться на простом примере.
Изучаемый набор данных содержит факт получения определенного количества баллов в зависимости от количества часов, потраченных на изучение материала.
Набор данных создан искусственно и (для упрощения понимания) очень мал.
#Импортируем модули
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import sklearn.linear_model as lm
from sklearn.metrics import r2_score ,
mean_absolute_error, mean_squared_error
# Загружаем данные
df = pd.read_csv('Grade_Set_1.csv')
print(df)
# Создаем объект Линейная регрессия
lr = lm.LinearRegression()
# x - выберем в качестве свойства (feature)
массив с исходными данными
# А теперь, внимание, вместо
решейпинг (изменение формата)
# x = df.iloc[:,1].values
# x=np.reshape(x, (-1,1))
# мы используем функцию np.newaxis,
создающую новую ось
# и, по сути, решающую ту же проблему
x= df.Hours_Studied[:, np.newaxis] # Это Features
y= df.Test_Grade.values #
Это Labels
# Тренируем
модель
lr.fit(x, y)
#При необходимости мы можем рассчитать
точку пересечений с осью и коэффициент
# наклона линии регрессии
print ("Intercept: ", lr.intercept_)
print ("Coefficient: ", lr.coef_)
# Добавим новый столбец в объект
DataFrame и поместим в него предсказанное значение
df['Test_Grade_Pred']=lr.predict(x)
print(df)
# Визуализация результатов тестового
набор данных
# Выводит оригинальный набор данных
plt.scatter(x,y,color = 'red')
# Выводит линию регрессии рассчитанную
через вызов regressor.predict(x)
plt.plot(x, lr.predict(x), color='blue', linewidth=3)
plt.title('Grade vs Hours Studied')
plt.ylabel('Test_Grade')
plt.xlabel('Hours_Studied')
plt.show()
# Как видим линия регрессии
"легла" достаточно близко к точкам в переменной "y"
# Давайте рассчитаем точность нашего
предсказания
# Для начала рассчитаем отклонение
исходных значений, хранящихся в переменной "y"
# от среднего значения
# SST - sum of squares template
df['SST'] = np.square(df['Test_Grade'] - df['Test_Grade'].mean())
# Далее рассчитаем отклонение
предсказанных значений, хранящихся в столбце
# DataFrame
# df['Test_Grade_Pred'], от среднего
значения
# SSR - sum of squares regression
df['SSR'] = np.square(df['Test_Grade_Pred'] - df['Test_Grade'].mean())
print ("Sum of SSR:", df['SSR'].sum())
print ("Sum of SST:", df['SST'].sum())
# Рассчитаем коэффициент
детерминации, показывающий на сколько точно мы предсказали значения
print ("R Squared using manual calculation:
", df['SSR'].sum() / df['SST'].sum())
R Squared using manual calculation: 0.9757431074095351
# Как видим точность достаточно
большая, так как значение близко к единице, что, собственно, и видно на графике
# Произведем вычисление точности с
использованием встроенных функций
print ("R Squared using built-in function: ",
r2_score(df.Test_Grade,
df.Test_Grade_Pred))
print ("Mean Absolute Error: ",
mean_absolute_error(df.Test_Grade, df.Test_Grade_Pred))
print ("Root Mean Squared Error: ",
np.sqrt(mean_squared_error(df.Test_Grade, df.Test_Grade_Pred)))
R Squared using built-in function: 0.9757431074095347
Mean Absolute Error: 1.618518518518523
Root
Mean Squared Error: 2.0422995995497297
Коэффициент детерминации, полученный вручную, достаточно близок с тем, что получен с использованием специальной функции.
# Теперь давайте внесем некоторый
уровень "сумятицы" в равномерный ряд
# исходный
данных.
# Для начала перезагрузим
данные
df = pd.read_csv('Grade_Set_1.csv')
# Для внесения "сумятицы" добавим в
данные точку со значением, явно выходящим за пределы общей тенденции
df.loc[9] = np.array([5, 100])
print(df)
# Далее делаем все тоже самое, как и
в предыдущем примере, и посмотрим, что получилось
lr = lm.LinearRegression()
x= df.Hours_Studied[:, np.newaxis] # Это Features
y= df.Test_Grade.values # Это Labels
lr.fit(x, y)
print ("Intercept: ", lr.intercept_)
print ("Coefficient: ", lr.coef_)
df['Test_Grade_Pred']=lr.predict(x)
print(df)
plt.scatter(x,y,color = 'red')
plt.plot(x, lr.predict(x), color='blue', linewidth=3)
plt.title('Grade vs Hours Studied')
plt.ylabel('Test_Grade')
plt.xlabel('Hours_Studied')
plt.show()
# Как видно линия регрессии не может
пройти даже близко возле вновь добавленной точки, и точность предсказания остальных
точек тоже ухудшилась.
# Проверим
точность модели
print ("R Squared using built-in function: ",
r2_score(df.Test_Grade,
df.Test_Grade_Pred))
print ("Mean Absolute Error: ",
mean_absolute_error(df.Test_Grade, df.Test_Grade_Pred))
print ("Root Mean Squared Error: ",
np.sqrt(mean_squared_error(df.Test_Grade, df.Test_Grade_Pred)))
Почему добавление одной точки так сильно повлияло на результат? Почему коэффициент
детерминации стал значительно меньше?
Проблема состоит в том, что в нашем примере слишком мало значений, что не характерно для статистической обработки реальных данных. В нашем примере мы изменили 10% данных (добавив одну точку к существующим 9-ти), что значительно изменило статистику и повлияло на точность модели. Если бы точек было несколько сотен или тысяч, то добавление одной не изменило бы статистику данных.
Alexander Kalenik,
Senior Premier Field Engineer,
Microsoft Support,
PhD
8 июл. 2019 г.
Категория Машинное обучение