В продолжение Курса машинного обучения Python (линейная регрессия) Эндрю Нг я решил использовать свой код Python в соревновании Kaggle, чтобы проверить надежность и практичность кода.

Поскольку я тестирую алгоритмы линейной регрессии, конкурс Цены на жилье: расширенные методы регрессии кажется хорошим выбором для этой задачи. Набор данных состоит из 80 столбцов уникальных независимых переменных, 1460 строк в данных поезда и 1459 строк в тестовых данных. Цель этого конкурса - прогнозировать цены продажи домов на основе этих переменных. Данные можно скачать здесь.

Конкурс Kaggle - лучшее место для проверки своих навыков специалиста по данным благодаря большой библиотеке реальных наборов данных и различным соревнованиям для решения реальных бизнес-задач. Поскольку наборы данных, которые я сейчас использую, взяты из соревнований по игровым площадкам, доступно множество ядер, которые помогут новичкам работать с этим набором данных. Обязательно проверьте их, если вы новичок.

Начнем с импорта всех необходимых нам библиотек.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

Что касается данных, я обнаружил, что предварительная обработка данных перед разделением на набор данных для тестирования и обучения более эффективна. Это именно то, что я сделал, я объединяю данные перед их повторным разделением после обработки

df_train=pd.read_csv("train.csv")
df_test=pd.read_csv("test.csv")
y_train=df_train.iloc[:,-1].values
df_train.drop(["SalePrice"],axis=1,inplace=True)
df=pd.concat([df_train,df_test])

Теперь мы можем наблюдать за переменными и попытаться получить представление о наборах данных.

df.info()

Есть около 37 непрерывных функций и 43 категориальных функции, о чем следует помнить. Мы также можем обнаружить пропущенные значения на выходе.

Несмотря на то, что основное внимание уделяется алгоритму курса машинного обучения, все же требуется базовая очистка данных, прежде чем я смогу ввести данные в модель. Имейте в виду, что то, что я сделал, - это просто базовая предварительная обработка данных, есть более полный метод выбора функций, который значительно улучшит вывод модели.

Для базовой очистки данных я начинаю с удаления функций, у которых отсутствуют значения для более чем 50% данных.

missing=df.isnull().sum()/len(df)
miss_features=missing.loc[missing>0.5].index
df.drop(miss_features,inplace=True,axis=1)

По сути, вычислите долю пропущенных значений и с порогом 0,5 отбросьте объекты, которые превышают этот порог, из DataFrame.

df_train.corr()

Используя таблицы корреляции, я надеюсь удалить функции, которые сильно коррелируют друг с другом, или функции, которые не коррелируют с зависимой переменной (SalePrice).

df.drop(["Id","YrSold","MoSold","MiscVal","PoolArea","ScreenPorch","3SsnPorch","EnclosedPorch","KitchenAbvGr","BedroomAbvGr", "HalfBath","BsmtFullBath","BsmtHalfBath","LowQualFinSF","BsmtUnfSF","BsmtFinSF2","MSSubClass","OverallCond", "LotArea"],inplace=True,axis=1)

Я установил порог 0,9 для коллинеарности и 0,3 для функций, не связанных с SalePrice. Это означает, что любые 2 функции с коэффициентом корреляции более 0,9 или функции с коэффициентом от -0,3,0,3 с SalePrice будут удалены.

for bsmt in ["BsmtQual","BsmtCond","BsmtExposure","BsmtFinType1","BsmtFinType2"]:
    df[bsmt].fillna("No",inplace=True)
df["FireplaceQu"].fillna("No",inplace=True)
for gar in ('GarageType', 'GarageFinish', 'GarageQual',"GarageYrBlt","GarageCond"):
    df[gar].fillna('No',inplace=True)
    
for gar1 in ('GarageCars', 'GarageArea'):
    df[gar1].fillna(0,inplace=True)
for ea in ("LotFrontage","MasVnrArea","TotalBsmtSF","BsmtFinSF1"):
    df[ea].fillna(df[ea].mean(),inplace=True)
for _ in ("MasVnrType","MSZoning","Utilities","Exterior1st","Exterior2nd","Functional","KitchenQual","SaleType","Electrical"):
    df[_].fillna(df[_].mode()[0],inplace=True)

Блок кода выше заполняет отсутствующие значения, используя среднее значение или режим столбцов, в зависимости от того, является ли это непрерывной или категориальной функцией соответственно.

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

df=pd.get_dummies(df,columns=["MSZoning","Street","LotShape","LandContour","Utilities","LotConfig","LandSlope","Neighborhood","Condition1","Condition2","BldgType","HouseStyle","RoofStyle","RoofMatl","Exterior1st","Exterior2nd","MasVnrType","ExterQual","ExterCond","Foundation","BsmtQual","BsmtCond","BsmtExposure","BsmtFinType1","BsmtFinType2","Heating","HeatingQC","CentralAir","Electrical","KitchenQual","Functional","FireplaceQu","GarageType","GarageYrBlt","GarageFinish","GarageQual","GarageCond","PavedDrive","SaleType","SaleCondition"],prefix=["MSZoning","Street","LotShape","LandContour","Utilities","LotConfig","LandSlope","Neighborhood","Condition1","Condition2","BldgType","HouseStyle","RoofStyle","RoofMatl","Exterior1st","Exterior2nd","MasVnrType","ExterQual","ExterCond","Foundation","BsmtQual","BsmtCond","BsmtExposure","BsmtFinType1","BsmtFinType2","Heating","HeatingQC","CentralAir","Electrical","KitchenQual","Functional","FireplaceQu","GarageType","GarageYrBlt","GarageFinish","GarageQual","GarageCond","PavedDrive","SaleType","SaleCondition"],drop_first=True)

Теперь мы выполнили большую часть предварительной обработки, пришло время преобразовать его в numpy и разделить его на набор для обучения и тестирования перед обучением нашей модели.

X_train=df.iloc[:1460,:].values
X_test=df.iloc[1460:,:].values

Нормализация функций. Здесь я буду использовать sklearn, чтобы упростить себе жизнь.

sc_X=StandardScaler()
X_train=sc_X.fit_transform(X_train)
m,n=X_train.shape[0],X_train.shape[1]
X_train = np.append(np.ones((m,1)),X_train,axis=1)
theta=np.zeros((n+1,1))

Хорошо, теперь мы почти готовы обучать модель. Следующие несколько кодов - это просто функции, которые мы выполняли во время реализации Python.

def computeCost(X,y,theta):
    """
    Take in a numpy array X,y, theta and generate the cost function of using theta as parameter in a linear regression model
    """
    m=len(y)
    predictions=X.dot(theta)
    square_err=(predictions - y)**2
    
    return 1/(2*m) * np.sum(square_err)
def gradientDescent(X,y,theta,alpha,num_iters):
    """
    Take in numpy array X, y and theta and update theta by taking num_iters gradient steps
    with learning rate of alpha
    
    return theta and the list of the cost of theta during each  iteration
    """
    
    m=len(y)
    J_history=[]
    
    for i in range(num_iters):
        predictions = X.dot(theta)
        error = np.dot(X.transpose(),(predictions -y))
        descent=alpha * 1/m * error
        theta-=descent
        J_history.append(computeCost(X,y,theta))
    
    return theta, J_history
theta, J_history = gradientDescent(X_train,y_train.reshape(m,1),theta,0.01,400)

Хорошо, мы закончили. Теперь визуализируем функцию стоимости для каждой итерации, чтобы увидеть, работает ли она.

plt.plot(J_history)
plt.xlabel("Iteration")
plt.ylabel("$J(\Theta)$")
plt.title("Cost function using Gradient Descent")

Выглядит довольно хорошо для меня!

def predict(x,theta):
    """
    Takes in numpy array of x and theta and return the predicted value of y based on theta
    """
    
    predictions= np.dot(x,theta)
    
    return predictions

Та же функция прогнозирования, что и раньше…

X_test= sc_X.fit_transform(X_test)
X_test=np.append(np.ones((X_test.shape[0],1)),X_test,axis=1)
predict=predict(X_test,theta)
# export as csv
np.savetxt("submission.csv",predict,fmt="%.1f")

… И экспортировать прогноз в виде файла csv для отправки в Kaggle.

Итак, вот оно, соревнование по соревнованиям с использованием алгоритмов машинного обучения Эндрю Нг. Вы можете спросить, какова цель этого. Я просто хочу, чтобы все поняли, что вам не нужно знать лучшую модель, лучшие алгоритмы, прежде чем начинать Kaggle. Возможна даже простая модель из вводного курса машинного обучения. Несомненно, результат не впечатляющий, но важно то, что вы применили то, что узнали. Продолжайте учиться и применять, и в будущем вы выйдете на вершину этих списков лидеров.

Я вернусь к этому конкурсу, когда буду проходить курс машинного обучения Эндрю Нг, мы увидим, получим ли мы лучший результат, используя более продвинутую модель.

Спасибо за прочтение.