Следующий код реализует многомерную линейную регрессию с нуля. Код строится с того места, где мы остановились в простой линейной регрессии (https://medium.com/@surajsubramanian2000/simple-linear-regression-from-scratch-9e073185cdab).
Представление нашей гипотезы в виде функции нескольких параметров является мощным и необходимым. Следовательно, многомерная линейная регрессия широко используется, и это действительно мощный алгоритм.
Импорт необходимых пакетов
- numpy: для представления векторов,
- pandas: для чтения CSV-файлов и
- sklearn: мы используем его для разделения набора данных на обучение и тестирование, предварительной обработки, кодирования и вычисления ошибок.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import LabelEncoder
labelencoder = LabelEncoder()
Затем мы загружаем CSV-файл и удаляем ненужные столбцы. Набор данных можно загрузить с https://github.com/SurajSubramanian/MachineLearning/blob/master/ML-Programs/MultivariateLinearRegression/FuelConsumptionCo2.csv
df = pd.read_csv("FuelConsumptionCo2.csv")
Мы просмотрим набор данных
df['MODELYEAR'].unique() # returns array([2014])
Существует только 1 MODELYEAR, поэтому нет смысла включать его в качестве параметра. Так что бросаем
df = df.drop(['MODELYEAR'], axis=1)
Мы используем labelencoder для присвоения уникальных значений всем категориальным типам данных, поскольку мы не можем работать со строковыми переменными.
df['MAKE'], df['MODEL'], df['VEHICLECLASS'], df['TRANSMISSION'], df['FUELTYPE'] = \
labelencoder.fit_transform(df['MAKE']), labelencoder.fit_transform(df['MODEL']), labelencoder.fit_transform(df['VEHICLECLASS']), \
labelencoder.fit_transform(df['TRANSMISSION']), labelencoder.fit_transform(df['FUELTYPE'])
Далее мы отфильтровываем переменные, имеющие меньшую корреляцию с целевым параметром — CO2EMISSIONS.
cor = df.corr() cor_target = abs(cor["CO2EMISSIONS"]) #Selecting highly correlated features relevant_features = cor_target[cor_target>0.5] relevant_features
# Output :ENGINESIZE 0.874154 CYLINDERS 0.849685 FUELCONSUMPTION_CITY 0.898039 FUELCONSUMPTION_HWY 0.861748 FUELCONSUMPTION_COMB 0.892129 FUELCONSUMPTION_COMB_MPG 0.906394 CO2EMISSIONS 1.000000 Name: CO2EMISSIONS, dtype: float64
Удаление столбцов с низкой корреляцией, т. е.) столбцов с корреляцией ниже 0,5
df = df.drop(['MAKE', 'MODEL', 'VEHICLECLASS', 'FUELTYPE', 'TRANSMISSION'], axis=1)
df.head()
Мы используем минимальную нормализацию. Этот шаг действительно важен. Вы можете пропустить следующую ячейку и попробовать все остальные ячейки, чтобы получить какое-то абсурдное значение в качестве ошибки MSE.
y,x = df["CO2EMISSIONS"], df.drop(["CO2EMISSIONS"], axis=1)
Разделение набора данных на функции обучения и тестирования
x_, y_ = x.to_numpy(), y.to_numpy()
x_ = np.append(arr = np.ones((len(x_), 1)).astype(int), values = x, axis = 1)
x_train,x_test,y_train,y_test = train_test_split(x_,y_, test_size = 0.2, random_state=21)
Реализация тренировочного цикла
a=0.01 X = [] for row in x_train: r = [1] for item in row: r.append(item) X.append(r) X = np.asmatrix(X)
theta = np.zeros(((X[0].size), 1)) Y = y_train.reshape(-1,1) h = np.dot(X, theta) h.shape # returns (853, 1)
temp = np.zeros(theta.shape) cost = np.sum (np.dot(np.transpose(h-Y), (h-Y)))*(1/(2*X.shape[0])) temp = np.zeros(theta.shape)
Функция градиентного спуска и последующий код аналогичны тем, которые мы использовали для линейной регрессии, за исключением того, что здесь мы представляем тета в виде массива.
Одна вещь, которую я обычно делаю, - это исследую и играю с формами всех матриц и массивов и смотрю, как их можно комбинировать для получения требуемой результирующей матрицы.
def gradientDescent(theta, X): h = np.dot(X, theta) cost = np.sum(np.sum((h-Y)**2))*(1/(2*X.shape[0])) temp = theta - np.dot(X.T, h-Y) * (a/X.shape[0]) theta = temp return(theta, X, cost)
oldCost = 0 theta = np.ones(theta.shape) X = np.ones(X.shape) for i in range(0, 10000): (theta, X, cost) = gradientDescent(theta, X) if i%1000 == 0: print(cost) print(theta)
прогнозирование значений y для тестового набора данных и оценка нашей модели с помощью функции MSE
X_test = [] for row in x_test: r = [1] for item in row: r.append(item) X_test.append(r)
mean_squared_error(np.dot(X_test, theta), y_test) # returns 0.05530668773441035
Вы можете получить полный код из моего репозитория github https://github.com/SurajSubramanian/MachineLearning/tree/master/ML-Programs/MultivariateLinearRegression.
Вы можете добиться лучших результатов, используя встроенную функцию sklearn!
Спасибо за чтение :)