Горсть образцов

В этом блоге мы можем увидеть сквозное решение (от анализа данных до развертывания) для проблемы не переобучать Kaggle.

Оглавление

  1. Постановка задачи
  2. Подход первого разреза
  3. Исследовательский анализ данных
  4. Предварительная обработка и проектирование функций
  5. Моделирование различных подходов
  6. Сравнение моделей
  7. Развертывание с помощью Streamlit
  8. Ссылка
  9. Будущая работа

Постановка задачи

· Мы должны построить модель классификации без переобучения, используя 250 строк данных для обучения, и предсказать метки классов остальных 19750 строк. У нас есть непрерывные переменные в качестве функций в этом наборе данных.

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

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

Набор данных

Мы можем найти набор данных для этой задачи Kaggle здесь.

Файлы:
● train.csv — обучающая выборка. 250 строк.
● test.csv — тестовый набор. 19 750 строк.
● sample_submission.csv — пример файла отправки в правильном формате
Столбцы:
● id — идентификатор образца
● target — двоичная цель загадочного происхождения.< br /> ● 0–299- непрерывные переменные.

ПРИМЕЧАНИЕ.

Набор данных, который в настоящее время доступен на сайте Kaggle, является новой версией, но оценка старой версии все еще выполняется. вы можете получить старую версию здесь

Подход первого разреза

1. Первым шагом будет выполнение EDA, чтобы лучше понять данные.

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

3. Попробуйте методы стандартизации, нормализации и проверьте, улучшают ли они показатели (точность, показатель aucroc и т. д.).

4. Создайте базовую модель и проверьте значения показателей.

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

6. Попробуйте добавить новые функции (разработка функций) и проверьте, улучшается ли их модель.

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

8. Сравните разные модели.

9. Попробуйте построить сравнение моделей, результаты, чтобы проверить, подходит ли модель.

10. Для каждого эксперимента получение статистики или графика может помочь нам лучше понять шаги. Откалибруйте модель, которая добавляет больше к модели.

Исследовательский анализ данных

Данные содержат 300 признаков (0–299), которые являются непрерывными переменными. целевая переменная — это метка класса.

Проверить наличие пропущенных значений

#check for null values
print(df_train.isnull().values.any())
print(df_test.isnull().values.any())

В данных нет нулевых значений

Проверьте, сбалансирован ли набор данных

Набор данных немного несбалансирован.

Распространение данных

#dataframe with class 1
train_1=df_train[df_train['target']==1]
train_1[train_1.columns[2:]].std().plot(kind='hist');
plt.title('Distribution of standard deviation of all columns for those with class 1 as label')
#dataframe with class 0
train_0=df_train[df_train['target']==0]
train_0[train_0.columns[2:]].std().plot(kind='hist');
plt.title('Distribution of standard deviation of all columns for those with class 0 as label')

Распределение функций почти такое же, а распределение точек данных цели 0 и цели 1 перекрывается. Все функции кажутся нормализованными и нормально распределенными со средним значением = 0 (приблизительно) и стандартным значением = 0,1.

Корреляция

correlation = df_train.corr()
k= 15
cols = correlation.nlargest(k,'target')['target'].index
print(cols)
cm = np.corrcoef(df_train[cols].values.T)
f , ax = plt.subplots(figsize = (14,12))
sns.heatmap(cm, vmax=.8, linewidths=0.01,square=True,annot=True,cmap='viridis',
            linecolor="white",xticklabels = cols.values ,annot_kws = {'size':12},yticklabels = cols.values)

Существует не так много корреляции между признаками. Максимальная корреляция меньше 0,3. Поэтому нам не нужно отказываться от каких-либо функций. Мы можем попытаться проверить, оказывают ли эти слегка коррелированные функции какое-либо влияние, проверив оценку с помощью &, не отбрасывая их.

2D-визуализация

sns.set(rc={'figure.figsize':(20,10)})
pca = PCA(n_components=3, svd_solver='full')
pca_result = pca.fit_transform(df_train.drop(['id','target'], axis=1).values)
x = pca_result[:,0]
y = pca_result[:,1]
ax = sns.scatterplot(x, y, hue = df_train['target'], palette=sns.color_palette("hls", 2), legend="full", alpha=1)
ax.set_title('2D visualization')
ax.set_xlabel('pca-one')
ax.set_ylabel('pca-two')

Данные имеют 300 измерений, которые сводятся к 2 измерениям с использованием PCA и строятся на нем, чтобы увидеть, являются ли данные линейно разделимыми или нет.

Данные не являются линейно разделимыми.

3D-визуализация

ax = plt.figure(figsize=(20,10)).gca(projection='3d')
z = pca_result[:,2]
ax.scatter(xs=x, ys=y, zs=z, c=df_train['target'], cmap='Accent')
ax.set_title('3D visualization')
ax.set_xlabel('pca-one')
ax.set_ylabel('pca-two')
ax.set_zlabel('pca-three')
plt.show()

С увеличением размерности целевые 0 и целевые точки 1 подвергаются простой сегрегации. Таким образом, они будут более различимы в высоком измерении.

Предварительная обработка и разработка функций

Масштабирование

Данные немного несбалансированы. Итак, у нас есть способы

  1. Передискретизация класса меньшинства
  2. Класс большинства при выборке

Передискретизация:

smote = SMOTE()
X = df_train.drop(['id','target'], axis=1)
y = df_train['target']
Xo_train, yo_train = smote.fit_resample(X, y)
print(Xo_train.shape, yo_train.shape)

Под выборкой:

under = RandomUnderSampler(sampling_strategy=1.0)
Xou_train, you_train = under.fit_resample(X, y)
print(Xou_train.shape, you_train.shape) 

Более низкая выборка

smote = SMOTE(sampling_strategy=0.75)
Xo_train, yo_train = smote.fit_resample(X, y)
print(Xo_train.shape, yo_train.shape) 

under = RandomUnderSampler(sampling_strategy=1.0)
Xou_train, you_train = under.fit_resample(Xo_train, yo_train)
print(Xou_train.shape, you_train.shape) 

Разработка функций

Мы можем использовать различные функции, такие как:

1.среднее и стандартное значение функций

2. Тригнометрические признаки

3.Гиперболические черты

4.Экспоненциальные функции

5. Полиномиальные признаки

def feature_enng(df):
    temp = df.drop(['id','target'], axis=1)

    # Mean and Std FE
    df['mean'] = np.mean(temp, axis=1)
    df['std'] = np.std(temp, axis=1)

    # Trigometric FE
    sin_temp = np.sin(temp)
    cos_temp = np.cos(temp)
    tan_temp = np.tan(temp)
    df['mean_sin'] = np.mean(sin_temp, axis=1)
    df['mean_cos'] = np.mean(cos_temp, axis=1)
    df['mean_tan'] = np.mean(tan_temp, axis=1)

    # Hyperbolic FE
    sinh_temp = np.sinh(temp)
    cosh_temp = np.cosh(temp)
    tanh_temp = np.tanh(temp)
    df['mean_sinh'] = np.mean(sin_temp, axis=1)
    df['mean_cosh'] = np.mean(cos_temp, axis=1)
    df['mean_tanh'] = np.mean(tan_temp, axis=1)

    # Exponents FE
    exp_temp = np.exp(temp)
    expm1_temp = np.expm1(temp)
    exp2_temp = np.exp2(temp)
    df['mean_exp'] = np.mean(exp_temp, axis=1)
    df['mean_expm1'] = np.mean(expm1_temp, axis=1)
    df['mean_exp2'] = np.mean(exp2_temp, axis=1)

    # Polynomial FE
    # X**2
    df['mean_x2'] = np.mean(np.power(temp,2), axis=1)
    # X**3
    df['mean_x3'] = np.mean(np.power(temp,3), axis=1)
    # X**4
    df['mean_x4'] = np.mean(np.power(temp,4), axis=1)

    return df

Методы выбора признаков

Взаимная информация

X = df_train.drop(['id','target'],axis=1)
y = df_train['target']
select_k = 20
selection = SelectKBest(mutual_info_classif, k=select_k).fit(X, y)
print('Best {} selected Features are: {}'.format(select_k, list(X.columns[selection.get_support()])))

Рекурсивное устранение признаков

from sklearn.svm import SVR
estimator = SVR(kernel="linear")
selector = RFE(estimator, n_features_to_select=5, step=1)
selector = selector.fit(X, y)

Встраивание моделей

from sklearn.linear_model import LogisticRegression, LassoCV , LassoLarsCV, RidgeCV
embd_models =  [
    ('LassoCv' , LassoCV(alphas =  [0.05, 0.1, 0.3, 1, 3, 5, 10, 15, 30, 50, 75], n_jobs=-1) ),
    ('LassoLarsCV', LassoLarsCV(n_jobs=-1) ),
    ('RidgeCV', RidgeCV() )
]

Modeltype = 'EmbeddedF'

for model in embd_models:
    clf = model[1]
    clf.fit(X, y)
    pred = clf.predict(df_test)

Моделирование

Модели машинного обучения

Все модели были классифицированы по типам, таким как базовая модель, модель над выборкой, модель с инженерными функциями и т. Д. Для каждого типа существует 8 различных алгоритмов классификации, за которыми следует обучение калибровке для данного набора данных. Они перечислены ниже:

  1. Логистическая регрессия (линейная)
  2. Линейный дискриминационный анализ (линейный)
  3. K классификаторов соседей (нелинейные)
  4. Дерево решений (нелинейное)
  5. Наивный байесовский (нелинейный)
  6. Классификаторы опорных векторов (нелинейные)
  7. Случайный лес (нелинейный)
  8. XGBoost (нелинейный)

Для моделирования мы использовали разные функции. Они

Метрика, используемая в этом моделировании,

Площадь графика под кривой рабочих характеристик приемника (AUC ROC):

def plot_roc(train_true, train_pred, test_true, test_pred, axis, model_name, cv_score, train_acc, test_acc, n_classes=2):
    '''
    Compute ROC curve and ROC area for each class
    
    Parameters:
    train_true: train true label
    train_pred: train predict probabilities value
    test_true: Sample Test true label
    test_pred: Sample Test predict probabilities value
    axis: axis of plot
    model_name: Name of Model curve
    cv_score: CV score of model
    train_acc: Train accuracy of Model
    test_acc: Test accuracy of Model
    n_classes: number of unique classes
    
    Return:
    Nothing   
    '''
    # For train
    tr_fpr = dict()
    tr_tpr = dict()
    tr_roc_auc = dict()
    for i in range(n_classes):
        tr_fpr[i], tr_tpr[i], _ = roc_curve(train_true, train_pred[:, i])
        tr_roc_auc[i] = auc(tr_fpr[i], tr_tpr[i])

    # For Sample Test
    te_fpr = dict()
    te_tpr = dict()
    te_roc_auc = dict()
    for i in range(n_classes):
        te_fpr[i], te_tpr[i], _ = roc_curve(test_true, test_pred[:, i])
        te_roc_auc[i] = auc(te_fpr[i], te_tpr[i])

    # Plot roc for train
    axis.plot(tr_fpr[1], tr_tpr[1], color='red', alpha=0.5, 
            lw=2, label='ROC curve for Train (area = %0.2f)' % tr_roc_auc[1])
    # Plot roc for Sample Test
    axis.plot(te_fpr[1], te_tpr[1], color='green', alpha=0.5, 
            lw=2, label='ROC curve for Sample Test (area = %0.2f)' % te_roc_auc[1])
    axis.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
    axis.set_xlim([0.0, 1.0])
    axis.set_ylim([0.0, 1.05])
    axis.set_xlabel('False Positive Rate')
    axis.set_ylabel('True Positive Rate')
    axis.set_title(model_name+' Receiver operating characteristic: train vs Sample Test')
    axis.legend(loc="lower right")

    axis.text(x=1.0, y=0.40, transform=axis.transAxes, s="Mean CV ROC_AUC: {:.4f}".format(cv_score),\
            fontweight='demibold', fontsize=10, verticalalignment='top', horizontalalignment='right',\
            backgroundcolor='white', color='r')
    axis.text(x=1.0, y=0.34, transform=axis.transAxes, s="Train Accuracy: {:.4f}".format(train_acc),\
            fontweight='demibold', fontsize=12, verticalalignment='top', horizontalalignment='right',\
            backgroundcolor='white', color='b')
    axis.text(x=1.0, y=0.28, transform=axis.transAxes, s="Sample Test Accuracy: {:.4f}".format(test_acc),\
            fontweight='demibold', fontsize=12, verticalalignment='top', horizontalalignment='right',\
            backgroundcolor='white', color='g')

Конвейер для всех алгоритмов классификации:

def Model():
    '''
    There are total 8 algorithms with list of their hyperparameters
    1. Logistic Regression (linear)
    2. Linear Discriminate Analysis(linear)
    3. K Neighbors Classifiers (non-linear)
    4. Decision Tree (non-linear)
    5. Naive Bayes (non-linear)
    6. Support Vector Classifiers (non-linear)
    7. Random Forest (non-linear)
    8. XGBoost (non-linear)

    Return:
    all the models along with their name, list of hyperparamaters and short_name
    '''
    # Hyperparameters for Logistic Regression
    LRparams = {
        "class_weight":["balanced"],
        "penalty" : ["l2","l1"],
        "tol" : [0.0001,0.0002,0.0003],
        "max_iter": [100,200,300],
        "C" :[0.001,0.01, 0.1, 1, 10, 100],
        "intercept_scaling": [1, 2, 3, 4],
        "solver":["liblinear"],
    }
    # Hyperparameters for Linear Discriminate Analysis
    LDAparams = {
        "solver" : ["svd"],
        "tol" : [0.0001,0.0002,0.0003]
    }
    # Hyperparameters for K Neighbors Classifiers
    KNNparams = {
        'n_neighbors':[5,6,7,8,9,10],
        'leaf_size':[1,2,3,5],
        'weights':['uniform', 'distance'],
        'algorithm':['auto', 'ball_tree','kd_tree','brute'],
        'n_jobs':[-1]
    }
    # Hyperparameters for Decision Tree
    DTparams = {
        "max_depth": [3, 5 , 10, None],
        "max_features": ["auto", "sqrt", "log2", None],
        "min_samples_leaf": [1,5,10,50],
        "criterion": ["gini", "entropy"],
        "class_weight":["balanced"]
    }
    # Hyperparameters for Naive Bayes
    NBparams = {
        'var_smoothing': np.logspace(0,-9, num=100)   
    }
    # Hyperparameters for Support Vector Classifiers
    SVCparams = {
        'kernel': ['rbf','linear'], 
        'gamma': [0.0001, 0.001, 0.01, 0.1, 1,'auto'],
        'C': [1, 6, 7, 8, 9, 10, 11, 12, 10, 50, 100, 200, 300],
        'class_weight': ['balanced'],
        'probability': [True]
    }
    # Hyperparameters for Random Forest
    RFparams = {
        'criterion':['gini','entropy'],
        'n_estimators':[10,15,20,25,30],
        'min_samples_leaf':[1,2,3,4,5],
        'min_samples_split':[3,4,5,6,7], 
        'n_jobs':[-1],
        'class_weight' : ["balanced", "balanced_subsample"]
    }
    # Hyperparameters for XGBoost
    XGBparams={
        'learning_rate':[0.01,0.03,0.05,0.1,0.15,0.2],
        'n_estimators':[10,20,30,40,100],
        'max_depth':[2,3,5,10],
        'colsample_bytree':[0.1,0.3,0.5,1],
        'subsample':[0.1,0.3,0.5,1],
        'n_jobs':[-1],
    }
    # Models
    models = []
    models.append(('Logistic Regression1', LogisticRegression(random_state=42), LRparams,'LR'))
    models.append(('Linear Discriminate Analysis1', LinearDiscriminantAnalysis(), LDAparams,'LDA'))
    models.append(('K Neighbors Classifiers1', KNeighborsClassifier(), KNNparams,'KNN'))
    models.append(('Decision Tree1', DecisionTreeClassifier(random_state=42), DTparams,'DT'))
    models.append(('Naive Bayes1', GaussianNB(), NBparams,'NB'))
    models.append(('Support Vector Classifiers1', SVC(random_state=42), SVCparams,'SVC'))
    models.append(('Random Forest1', RandomForestClassifier(random_state=42), RFparams,'RF'))
    models.append(('XGBoost1', XGBClassifier(random_state=42), XGBparams,'XGB'))
    return models

Шаблон для обучающих моделей

def trainWithBestModelAndParams(X_train, X_test, y_train, y_test, Modeltype, Test = test, CV=5, Scaling=True):
    '''
    Select Best ML model with their best hyperparamaters
    
    Parameters:
    X_train: train data
    X_test: Sample test data
    y_train: train true label
    y_test: Sample Test true label
    Test: test data for submission
    CV: Number of cross-validation folds
    Scaling: For Scaling of Input varaibles 
    
    Return:
    Best Classifiers   
    '''
    models = Model()
    # Scaling Features
    if Scaling:
        X_train, X_test, Test = scale(X_train, X_test, Test)

    #RandomSearch    
    result = []
    print('{:31}| {:6} | {}'.format('Estimator', 'Score', 'Best Parameters'))
    print('-'*180)
    for name, model, params, abr in models:
        rs=RandomizedSearchCV(model ,param_distributions = params ,verbose=0, n_jobs=-1, scoring='roc_auc',cv = CV, n_iter=10, random_state=42)
        rs.fit(X_train,y_train)
        result.append((name, rs.best_score_, rs.best_params_, rs.best_estimator_, abr))
        print('{:31}| {:.4f} | {}'.format(name, rs.best_score_, rs.best_params_))

    # Selecting Best Score Model
    mx = -1
    best_model = 0
    for i in result:
        if(i[1]>mx):
            mx = i[1]
            best_model = i
    print('_'*180)
    print('{:15}:{}'.format('Best Model', best_model[0]))
    print('{:15}:{:.4}'.format('CV Score', best_model[1]))
    print('{:15}:{}'.format('Parameters', best_model[2]))
    print('{:15}:{}'.format('Estimator', best_model[3]))
    print('_'*180)
    
    #Training Models
    print('Training Models..')
    sns.set(rc={'figure.figsize':(30,30)})
    fig, ax = plt.subplots(4, 2,sharex='col', sharey='row')
    ax = ax.reshape(-1)

    classifiers = []
    for i, model in enumerate(result):
        clf = model[3]
        clf = CalibratedClassifierCV(clf, cv=10, method='sigmoid')
        clf.fit(X_train,y_train)

        #Save Model into disk
        save_model(clf, Modeltype, model[4])

        #Append classifier into list
        classifiers.append((model[0], clf))

        #Predicting
        #pred = clf.predict(Test)
        #print(Test)
        pred = clf.predict_proba(Test)[:,1]

        #Saving prediction into disk
        save_test_result(pred, Modeltype, model[4])
        #print(clf.predict_proba(X_train))
        #Plotting ROC AUC
        plot_roc(y_train, clf.predict_proba(X_train), y_test, clf.predict_proba(X_test),\
                 ax[i], model[0], model[1], clf.score(X_train,y_train), clf.score(X_test, y_test), n_classes=2)

        print(model[0]+' done.')
    print('_'*180)
    print('Plotting ROC curve')
    plt.show()
    classifiers = dict(classifiers)
    return best_model, classifiers

Теперь приступим к моделированию

Чтение и разделение данных

df_train = pd.read_csv('/content/drive/MyDrive/CasestudiesAAIC/self case study12/train.csv')
df_test = pd.read_csv('/content/drive/MyDrive/CasestudiesAAIC/self case study12//test.csv')
submission = pd.read_csv('/content/drive/MyDrive/CasestudiesAAIC/self case study12/sample_submission.csv')
print(df_train.shape)
print(df_test.shape)
print(submission.shape)
print('-'*100)
X = df_train.drop(['id','target'], axis=1)
y = df_train['target']
test = df_test.drop(['id'], axis=1)
#stratify parameter makes a split so that the proportion of values in the sample produced will be the same as the proportion of values provided to parameter stratify.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.04, stratify=y, random_state=42) 
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)
print(test.shape)
  1. Базовая модель

В этом подходе мы только что выполнили масштабирование и обучили упомянутые выше стандартные модели. логистическая регрессия дала нам сравнительно лучшие результаты (оценка Kaggle — 0,818), что является хорошей оценкой.

2. Базовый план + разработка функций

В этом подходе мы только что выполнили масштабирование и обучили стандартные модели, используя исходные данные вместе с новыми функциями, которые мы добавили при разработке функций. логистическая регрессия дала нам сравнительно лучшие результаты (оценка Kaggle — 0,821), что является хорошей оценкой.

3. Модель избыточной выборки

В этом подходе мы сначала выполнили выборку в классе меньшинства, используя алгоритм SMOTE, чтобы сбалансировать набор данных, затем обучили все классификаторы и получили хорошие результаты с помощью алгоритма XGBoost с оценкой 0,761 (частная оценка), что меньше, чем у базовой модели. Как мы видели в EDA, модель не очень сильно несбалансирована, может быть поэтому результаты не сильно улучшились. Давайте проверим, помогает ли недостаточная выборка.

4. Модель избыточной недостаточной выборки

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

5. Взаимная информация (разработка функций)

В этом подходе взаимная информация, которая представляет собой метод выбора признаков на основе фильтров, применяется для выбора только лучших признаков и последующего обучения со всеми классификаторами. Алгоритм SVC дал хорошую оценку 0,662 (частная оценка). Исходя из этого, можно легко сделать вывод, что это не лучший метод выбора признаков для данной задачи.

6. Рекурсивное устранение признаков

В этой модели RFE был применен метод выбора признаков на основе оболочки, использовались лучшие базовые классификаторы в качестве оценки метода RFE, и был получен результат 0,772 (частная оценка).

7.Встраивание моделей

В этой модели был применен встроенный метод выбора признаков и использованы 3 различных встроенных алгоритма: LassoCv, LassoLarsCV и RidgeCV, и алгоритм LassoCV получил результат 0,821 балла. Этот метод дал нам лучший результат.

Вывод:

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

Сравните модели:

Развертывание с помощью Streamlit:

Streamlit — это фреймворк для приложений с открытым исходным кодом на языке Python. Это помогает нам создавать веб-приложения для науки о данных и машинного обучения за короткое время. Он совместим с основными библиотеками Python, такими как scikit-learn, Keras, PyTorch, SymPy (латекс), NumPy, pandas, Matplotlib и т. д. Я создал простое веб-приложение с использованием Streamlit, которое принимает тестовый CSV-файл в качестве входных данных и возвращает вероятность целевого значения для каждой строки в качестве вывода. Скриншот веб-приложения прикреплен ниже.

Ссылка:

  1. https://towardsdatascience.com/13-key-code-blocks-for-eda-classification-task-94890622be57
  2. https://towardsdatascience.com/data-pre-processing-techniques-you-should-know-8954662716d6
  3. https://github.com/sahilsharma884/Dont_OverfitII/blob/master/2_FeatureEngg.ipynb
  4. https://towardsdatascience.com/7-over-sampling-techniques-to-handle-imbalanced-data-ec51c8db349f
  5. https://www.geeksforgeeks.org/feature-selection-techniques-in-machine-learning/
  6. https://towardsdatascience.com/dont-overfit-ii-how-to-avoid-overfitting-in-your-machine-learning-and-deep-learning-models-2ff903f4b36a
  7. # https://medium.com/analytics-vidhya/kaggle-competition-dont-overfit-ii-74cf2d9d
  8. https://towardsdatascience.com/deploying-ml-models-using-streamlit-5d6212453bdd
  9. www.appliedaicourse.com

Будущая работа:

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

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

Вот мой профиль LinkedIn и код на GitHub.