Studi Kasus End-too-End untuk Memprediksi Gaji Postingan Pekerjaan untuk Mesin Pencari Kerja menggunakan Pembelajaran Mesin dengan Implementasi Python

“Pendidikan bukan tentang mengurangi jumlah ternak. Pendidikan adalah tentang membantu setiap siswa sukses”

Andrew Ng

Dalam Studi Kasus Ilmu Data menyeluruh ini, kami akan menggunakan serangkaian Model Pembelajaran Mesin untuk memperkirakan gaji Postingan Pekerjaan untuk Mesin Pencari Kerja Memang. Kami akan melatih dan mengevaluasi performa beberapa model ML menggunakan K-Fold Cross Validation dan perkiraan RMSE/MSE/MAE-nya. Model dengan kinerja terbaik akan dipilih di akhir dan juga akan menyimpan prediksi gaji untuk postingan pekerjaan Tes.

Repositori GitHub dengan Data dan Kode Python di sini

Isi Blognya

1. Mendefinisikan Tujuan Bisnis dan Ilmu Data

2. Pemrosesan Awal Data

3. Visualisasi Data

4. Metodologi (Perbandingan dan Deskripsi Model ML)

5. Proses Pelatihan Langkah demi Langkah Model Pembelajaran Mesin

6. Mengevaluasi Model Pembelajaran Mesin Kami

7. Pentingnya Fitur

1. Mendefinisikan Tujuan Bisnis dan Ilmu Data

Jika Anda pernah mencoba menggunakan mesin pencari kerja modern seperti “Glassdoor», “” untuk “LinkedIn »”, maka Anda mungkin telah memperhatikan bahwa beberapa lowongan pekerjaan menyebutkan gaji di dalamnya sementara sebagian besar tidak memberikan informasi tersebut. Informasi Gaji per lowongan pekerjaan sangat membantu para kandidat karena menghemat banyak waktu di awal. Hal ini akan menghindari para kandidat menjalani proses dan pada akhirnya mengetahui bahwa mereka tidak akan dibayar sebagaimana mestinya atau sesuai harapan.

Ini adalah masalah besar bagi Mesin Pencari Kerja mana pun karena sebagian besar lowongan pekerjaan tidak menyertakan gaji pekerjaan, dan menambahkan fitur-fitur ini berpotensi meningkatkan kepuasan dan keterlibatan pengguna mesin Pencari.

Hal pertama yang perlu kita lakukan dalam setiap studi kasus adalah mendefinisikan dan merumuskan Sasaran Bisnis dan Sasaran Teknis (Ilmu Data) yang ingin Anda capai dengan menyelesaikan Studi Kasus atau proyek.

Tujuan Bisnis

Dalam studi kasus ini, kami bertujuan untuk membuat fitur perkiraan gaji untuk mesin pencari kerja. Perkiraan gaji untuk lowongan pekerjaan baru ini dapat meningkatkan pengalaman pencari kerja dengan memberikan mereka informasi gaji.

Tujuan Teknis (Ilmu Data).

Tujuan teknis dari Studi Kasus ini adalah menggunakan Machine Learning untuk memprediksi gaji peluang kerja berdasarkan deskripsi pekerjaannya.

Kami akan menjawab pertanyaan-pertanyaan berikut:

  1. Bahasa perangkat lunak dan pustaka apa yang Anda gunakan untuk memecahkan masalah tersebut? Mengapa Anda memilih bahasa/perpustakaan ini?
  2. Langkah apa yang kami ambil untuk menyiapkan data untuk proyek ini? Apakah ada pembersihan yang diperlukan?
  3. Apa metode pembelajaran mesin yang diterapkan?
  4. Mengapa kami memilih metode ini?
  5. Metode lain apa yang kami pertimbangkan?
  6. Jelaskan cara kerja algoritma pembelajaran mesin.
  7. Apakah diperlukan pengkodean atau transformasi fitur, dan yang mana?
  8. Fitur manakah yang memiliki dampak terbesar terhadap gaji? Bagaimana kami mengidentifikasi hal-hal ini sebagai hal yang paling signifikan? Fitur manakah yang memiliki dampak paling kecil terhadap gaji? Bagaimana kami mengidentifikasinya?
  9. Bagaimana kami melatih model Machine Learning? Selama pelatihan, permasalahan apa saja yang menjadi perhatian?
  10. Bagaimana Anda membuat estimasi metrik kinerja RMSE?
  11. Metrik apa, selain RMSE, yang berguna untuk menilai keakuratan perkiraan gaji? Mengapa?

2. Pemrosesan Awal Data

Mari kita lihat sekilas datanya.

Fitur Pelatihan

train_features.csv: Setiap baris mewakili metadata untuk setiap postingan pekerjaan

Fitur Tes

test_features.csv: Mirip dengan train_features.csv di mana setiap baris mewakili metadata untuk postingan pekerjaan individual

Gaji Pelatihan

train_salaries.csv : Setiap baris mengaitkan “jobId” dengan “gaji”. Ini adalah variabel yang bergantung pada pelatihan untuk mengawasi model Machine Learning

train_features = 'train_features.csv'
train_response = 'train_salaries.csv'
test_features = 'test_features.csv'
# loading training features
train_featuresDf = pd.read_csv(train_features, header=0)
# loading salaries: dependent variable
train_responseDf = pd.read_csv(train_response, header=0)
# combining job features and salaries 
trainDf = train_featuresDf.merge(train_responseDf,on=None, how="inner")
# loading test features
testDf = pd.read_csv(test_features, header=0)

Pembersihan dan Persiapan Data

Untuk mempersiapkan data proyek, saya melakukan langkah-langkah berikut

  • memuat kumpulan data dan menjelajahinya
  • menggabungkan fitur pelatihan dengan gaji pelatihan
  • mengidentifikasi fitur numerik dan fitur kategorikal
  • dapatkan beberapa statistik deskriptif sederhana tentang data tersebut dan lihat apakah ada nilai yang aneh atau perbedaan
  • diperiksa untuk titik data yang hilang (NULL dan NA)
  • memeriksa duplikat
  • memeriksa nilai yang tidak valid dan outlier (memeriksa nilai non-positif, Aturan Rentang Kuantil Antar, inspeksi visual, menjelajahi data, memvisualisasikan distribusi data untuk fitur numerik dan diagram kotak sehubungan dengan variabel respons: gaji)
  • menandai outlier dan menghapusnya dari data
  • menyandikan variabel kategori
  • jadikan JobId sebagai indeks
  • menyimpan data untuk proses selanjutnya

Selama proses eksplorasi dan visualisasi data, saya menemukan ada beberapa nilai yang tidak valid, seperti kasus di mana pekerjaan yang tampaknya dibayar penuh waktu memiliki gaji sama dengan 0. Yang kemudian saya hapus dari set pelatihan. Saya tidak melihat adanya nilai yang hilang dalam data. Meskipun datanya cukup bersih, proses pembersihan masih diperlukan untuk mengidentifikasi, menandai, dan menghapus nilai yang hilang.

# for numeric features only 
        yearsExperience  milesFromMetropolis
count   1000000.000000       1000000.000000
mean         11.992386            49.529260
std           7.212391            28.877733
min           0.000000             0.000000
25%           6.000000            25.000000
50%          12.000000            50.000000
75%          18.000000            75.000000
max          24.000000            99.000000
def process_validate_data(self):
        '''data exploration and validation process'''
        # load and store training data to dataFrame
        self._create_training_df()
        # load and store test data to dataFrame
        self._create_test_df()
        # get information about the features: categorical and numerical features
        self._get_features_info()
        # get training data statistics
        self._get_trainDf_statistics()
        # get test data statistics
        self._get_testDf_statistics()
        # checking for missing data points
        self._check_missing_data(self.trainDf)
        # checking the number of repeatitions/duplicates
        self._check_duplicates()
        # getting all columns containing negative or 0 values which is something we don't expect
        self._get_invalid_data(self.trainDf, pred_response)
def _get_features_info(self):
    '''getting categorical and numerical features'''
    self.features_cat = self._get_cat_features(self.trainDf)
    self.features_num = self._get_num_features(self.trainDf)
def _get_cat_features(self, df):
    '''finding  categorical columns in Dataframe'''
    self.features_cat = df.select_dtypes(include=['O']).columns.tolist()
    print('List of Categorical Features: {}'.format(self.features_cat))
    return (self.features_cat)
def _get_num_features(self, df):
    '''finding numerical columns in Dataframe'''
    self.features_num = df.select_dtypes(exclude=['O']).columns.tolist()
    print('List of Numerical Features: {}'.format(self.features_num))
    return (self.features_num)
def _get_trainDf_statistics(self):
    print('Training Data Statistics')
    self._get_statistics(self.trainDf)
def _get_testDf_statistics(self):
    print('Test Data Statistics')
    self._get_statistics(self.testDf)
def _get_statistics(self, df):
    print('\n  Dataframe Information: \n')
    print('n{}'.format(df.info()))
    print('\n Dataframe Size [#rows, #cols]- {}'.format(df.shape))
    print('\n Numerical Features Statistics: \n \n{}'.format(df.describe()))
    print('\n Categorical Features Stats: \n \n{}'.format(df.describe(include='O')))
def _check_missing_data(self, df):
    '''Checking and finding  null or na values in Dataframe'''
    num_missingval = np.sum(df.isna().sum()) + np.sum(df.isnull().sum())
    if num_missingval == 0:
        print('\n\n : There are no missing data points in the data')
    else:
        print('Features or columns that contain missing values\n\n{}'.format(df.isnull().sum()))
def _check_duplicates(self):
    '''Checking for duplicates'''
    print('\n : There are {} duplicate values in Train Data'.format(self.trainDf.duplicated().sum()))
    # though we found 5 repetitions in salary feature, this is not a duplicate since multiple jobs can have the same salary
    print('\n : There are {} duplicate values in Test Data'.format(self.testDf.duplicated().sum()))
def _get_invalid_data(self, df, cols):
    '''Finding and flagging invalid values'''
    for i in [cols]:
        # we don't expect any of the values to be equal to 0 so we will identify anything <= 0
        inv_counts = np.sum(df[i] <= 0)
        if inv_counts > 0:
            self.invalid_data = True
            print('\n :There are {} duplicates in {} column'.format(inv_counts, i))

Pengkodean Fitur

Karena ada fitur string kategoris yang ada dalam data, seperti ['companyId', 'jobType', 'degree', 'major', 'industry']. Untuk menggunakannya dalam model, variabel-variabel ini harus dikodekan untuk mengubah string menjadi nilai numerik.

Kami menggunakan LabelEncoder untuk melakukan pengkodean. Saya sedang berpikir untuk menggunakan One Hot Encoder, namun hal itu akan mempersulit penilaian dalam hal pentingnya fitur.

def clean_encode_df(self):
    '''Cleaning Data From Invalid Data points/Errors'''
    '''Since salaries equal to 0 (lower limit we found) don't make sense, /n we assume they are outliers and we will fag and remove them'''
    if self.invalid_data:
        print('Number of data points before removing invalid rows:- {}'.format(data.trainDf.shape[0]))
        data.trainDf = data.trainDf[data.trainDf['salary'] > 0]
        print('Number of data points after removing invalid rows with zero salary:- {}'.format(data.trainDf.shape[0]))
    ''' Encoding the categorical labels in training data'''
    trainDf = self.encode_cat_features(data.trainDf, self.features_cat)
    # since this is unique per observations it doesn't make sense to encode it
    # but we still need the jobIds, therefore we will use it as the index
    self.trainDf = trainDf.set_index("jobId").drop("index",1)

    ''' Encoding the categorical labels in test data'''
    testDf = self.encode_cat_features(data.testDf, self.features_cat, test_data=True)
    self.testDf = testDf.set_index("jobId")

def encode_cat_features(self, df, features, test_data=False):
    '''encoding the labels in categorical features'''
    if not test_data:
        for feature in features:
            l_encoder = LabelEncoder()
            l_encoder.fit(df[feature])
            self.labels[feature] = l_encoder
            df[feature] = l_encoder.transform(df[feature])
    else:
        # encoding for test data
        for feature, l_encoder in self.labels.items():
            df[feature] = l_encoder.transform(df[feature])
    return (df)

3. Visualisasi Data

Untuk mendapatkan gambaran tentang distribusi yang mendasari variabel kontinu, saya telah menggambar Plot Distribusinya. Plot ini menunjukkan bahwa variabel tidak mengikuti Distribusi Normal, yang perlu kita ingat saat memilih model yang memerlukan normalitas fitur.

def _distplot(self):
    '''Creates Distribution Plots for Numeric Features'''
    fig = plt.figure(figsize=(14, 10))
    for index, col in enumerate(self.features_num):
        fig.add_subplot(len(self.features_num), len(self.features_num), index + 1)
        n, x, _ = plt.hist(self.trainDf[col], bins=20, color='yellow', edgecolor='black', linewidth=0.5)
        bin_centers = 0.5 * (x[1:] + x[:-1])
        plt.plot(bin_centers, n, color='darkgreen', linewidth=2)
        plt.title('Distribution Plot for Numeric Features')
        plt.xlabel(str(col))
        plt.tight_layout()

Saya juga memplot diagram kotak untuk semua variabel, termasuk variabel dependen yang ingin kami prediksi, dan Gaji postingan pekerjaan di set pelatihan. Hal ini dapat membantu kami mengidentifikasi kasus-kasus yang tidak biasa dan outlier yang mungkin ingin kami periksa dan hapus dari data. Kita dapat melihat bahwa ada beberapa kasus di mana gajinya sama dengan 0, dan itu tidak masuk akal.

def _boxplot(self):
    '''Creates BoxPlots for Categorical and Numeric Features'''
    df = self.trainDf.copy()
    fig = plt.figure(figsize=(14, 9))
    for index, col in enumerate(self.features_cat):
        if len(self.trainDf[col].unique()) < 10:
            df[col + '_mean'] = df.groupby(col)[self.pred_response].transform('mean')
            fig.add_subplot(4, 2, index + 1)
            sns.boxplot(x=col, y=self.pred_response, data=df.sort_values(col + '_mean'))
            plt.title('Salaries vs {}'.format(col), fontsize=12)
            plt.tight_layout()
            plt.xticks(rotation=45)
    for index, col in enumerate(self.features_num):
        fig.add_subplot(len(self.features_num), len(self.features_num), index + 1)
        sns.boxplot(self.trainDf[col], color='yellow')
        plt.tight_layout()

4. Metodologi

Kami akan menggunakan model Pembelajaran Mesin berikut mulai dari teknik regresi yang sangat sederhana, seperti Regresi Linier, hingga model ansambel, seperti model ansambel GBM dan XGBoost.

  • Regresi Linier
  • Regresi Lasso (Regulerisasi L1)
  • Hutan Acak
  • Model Peningkatan Gradien (GBM)
  • XGBoost

Membandingkan Model ML

Kita akan melihat di bagian akhir bahwa saya akhirnya menggunakan algoritma GBM sebagai model pilihan akhir karena algoritma ini dikenal memberikan akurasi prediksi yang lebih baik untuk masalah jenis Regresi dan mampu menangani kumpulan data kompleks dengan jutaan baris dan fitur kategorikal/numerik. yang merupakan keuntungan besar dibandingkan Decision Trees, Bagging, dan bahkan Random Forest. GBM, seperti model Boosting lainnya, belajar dengan lambat namun lebih akurat, dan tidak seperti AdaBoost, GBM tidak sensitif terhadap outlier, dan dapat menangani model non-linier yang kompleks. Ini juga alasan saya tidak menggunakan AdaBoost.

Seperti Bagging (rata-rata Pohon Keputusan yang berkorelasi) dan Random Forest (rata-rata Pohon Keputusan yang tidak berkorelasi), Boosting bertujuan untuk meningkatkan prediksi yang dihasilkan dari pohon keputusan. Boosting adalah model Pembelajaran Mesin terawasi yang dapat digunakan untuk masalah regresi dan klasifikasi.

Tidak seperti Bagging atau Random Forest, di mana pohon-pohon dibangun secara independen satu sama lain menggunakan salah satu sampel bootstrap B (salinan tanggal pelatihan awal), di Boosting, pohon-pohon dibangun secara berurutan dan bergantung satu sama lain: setiap pohon ditanam menggunakan informasi dari pohon yang ditanam sebelumnya.

Boosting dikenal memiliki varian yang lebih rendah dan tidak terlalu rentan terhadap overfitting dibandingkan dengan tiga model berbasis lainnya seperti yang disebutkan sebelumnya. Model ini lebih baik dibandingkan model agregat lainnya seperti Bagging (membuat pohon berkorelasi) atau Random Forest (membuat pohon tidak berkorelasi karena komponen acaknya).

Bagaimana cara kerja Model Peningkatan Gradien?

Boosting bertujuan untuk memperbaiki prediksi yang dihasilkan dari pohon keputusan. Boosting adalah model Pembelajaran Mesin terawasi yang dapat digunakan untuk masalah regresi dan klasifikasi. Dalam Boosting, pepohonan dibangun secara berurutan dan bergantung satu sama lain: setiap pohon ditanam menggunakan informasi dari pohon yang ditanam sebelumnya.

Setiap pohon cocok dengan versi kumpulan data asli yang dimodifikasi. Ini adalah metode untuk mengubah pembelajar yang lemah menjadi pembelajar yang kuat. Dalam peningkatan, setiap pohon baru disesuaikan dengan versi kumpulan data asli yang dimodifikasi. Jadi, tidak seperti menyesuaikan satu pohon keputusan besar ke data, yang berarti melakukan penyesuaian data secara keras dan berpotensi melakukan overfitting, pendekatan peningkatan justru belajar dengan lambat.

Mengingat setiap pohon saat ini, pohon keputusan cocok dengan sisa model. Artinya, algoritme mencocokkan pohon dengan menggunakan residu saat ini, bukan hasil Y, sebagai responsnya. Kemudian pohon keputusan baru ini ditambahkan ke fungsi yang dipasang untuk memperbarui residu. Masing-masing pohon ini bisa berukuran agak kecil, hanya dengan beberapa simpul terminal, yang ditentukan oleh parameter d dalam algoritma.

GBM memulai proses pembelajarannya dengan memilih sehelai daun pohon dan melanjutkan pembangunannya dengan menggunakan pembelajar lemah dari stempel sebelumnya. Hasil yang sesuai dengan daun yang dipilih ini kemudian menjadi tebakan awal untuk variabel hasil.

Untuk memastikan pohon tidak overfitting, Peningkatan Gradien menggunakan Kecepatan Pembelajaran (eta) untuk menskalakan kontribusi gradien. Peningkatan Gradien didasarkan pada gagasan bahwa mengambil banyak langkah kecil ke arah yang benar (gradien) akan menghasilkan varians yang lebih rendah (untuk data pengujian). GBM mengidentifikasi kekurangan model sebelumnya dengan menggunakan gradien fungsi kerugian. Fungsi kerugian adalah ukuran yang menunjukkan seberapa baik koefisien model dalam menyesuaikan dengan data yang mendasarinya.

Untuk membangun GBM proses langkah demi langkah berikut dapat digunakan:

  • Langkah 1:Hitung rata-rata variabel hasil dan gunakan untuk menghitung Sisa Pseudo
  • Langkah 2:Gunakan fitur yang ada dan Residu Pseudo sebagai variabel hasil untuk memprediksi residu.
  • Langkah 3:Kami menggunakan sisa prediksi untuk memperbarui prediksi dari langkah sebelumnya sambil menskalakan kontribusi ini ke pohon dengan kecepatan pemelajaran.
  • Langkah 4:Proses ini dilanjutkan untuk memperbarui residu semu dan pohon sambil melakukan penskalaan dengan kecepatan pemelajaran, yang membantu untuk bergerak perlahan ke arah yang benar hingga tidak ada lagi peningkatan atau aturan penghentian kami.
from sklearn import linear_model
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from xgboost import XGBRegressor
LR = linear_model.LinearRegression()
Lasso_LR = linear_model.Lasso()
RForest = RandomForestRegressor(n_estimators=60, n_jobs=4, max_depth=15, min_samples_split=80, max_features=8,verbose=0)
GBM = GradientBoostingRegressor(n_estimators=60, max_depth=7, loss='ls', verbose=0)
xgboost = XGBRegressor(n_estimators=60, max_depth=7, eta=0.1, subsample=0.7, colsample_bytree=0.8)
models = [LR, Lasso_LR, RForest, GBM, xgboost]

5. Pelatihan Model Pembelajaran Mesin

Berikut adalah pendekatan langkah demi langkah untuk melatih Model Pembelajaran Mesin

Langkah 1: Kumpulkan dan persiapkan data

Langkah pertama dalam melatih model pembelajaran mesin adalah mengumpulkan dan menyiapkan data yang akan digunakan untuk melatih model tersebut. Hal ini mungkin melibatkan pembersihan data, menangani nilai yang hilang, dan memilih subkumpulan data untuk pelatihan.

Langkah 2: Bagi data menjadi set pelatihan dan validasi

Data biasanya dibagi menjadi dua set: set pelatihan dan set validasi. Model akan dilatih pada set pelatihan dan dievaluasi pada set validasi.

Langkah 3: Pilih model dan atur hyperparameter

Selanjutnya, Anda harus memilih model pembelajaran mesin dan mengatur hyperparameter. Hyperparameter adalah parameter model yang tidak dipelajari dari data selama pelatihan, seperti kecepatan pembelajaran atau kekuatan regularisasi.

Langkah 4: Latih modelnya

Model dilatih menggunakan data pelatihan dan algoritma optimasi yang dipilih. Algoritme pengoptimalan memperbarui parameter model untuk meminimalkan fungsi kerugian, yang mengukur perbedaan antara keluaran sebenarnya dan keluaran yang diprediksi.

Langkah 5: Evaluasi modelnya

Setelah model dilatih, model tersebut dievaluasi pada set validasi untuk menilai performanya. Metrik evaluasi akan bergantung pada masalah ML tertentu, seperti akurasi tugas klasifikasi atau tugas regresi.

Langkah 6: Sempurnakan modelnya

Jika model tidak berperforma baik pada set validasi, Anda mungkin perlu menyesuaikan hyperparameter atau mencoba pendekatan lain. Proses ini disebut penyempurnaan model.

Langkah 7: Uji model akhir

Setelah Anda puas dengan performa model pada set validasi, Anda dapat menyelesaikan model dan mengevaluasinya pada set pengujian. Ini akan memberi Anda perkiraan performa model pada data yang tidak terlihat.

class SalaryPredictingModel:
    def __init__(self, data, models):
        '''training multiple ML models for predicting salaries'''
        self.data = data
        self.models = models
        self.mse = {}
        self.rmse = {}
        self.mae = {}
        self.best_model = None
        self.predictions = None
        self.pred_response = data.pred_response
        self.train_response = data.trainDf[data.pred_response]
        self.train_features = data.trainDf.drop(data.pred_response, axis=1)
        self.testDf = data.testDf
        self.train_models()
    def train_models(self):
        self.KFold_CV_model()
        self.get_best_model()
    print('Training Process with K-Fold Cross Validation')
    ''' we will use K-fold CV for estimating average test error rate'''
    # defaults is K=5 in K-fold
    def KFold_CV_model(self):
        for model_output in self.models:
            print("Training model" + str(model_output) +" and calculating CV MSE, CV MAE, CV RMSE")
            scores_mse = cross_val_score(model_output, self.train_features, self.train_response, cv=5,scoring='neg_mean_squared_error')
            scores_mae = cross_val_score(model_output, self.train_features, self.train_response, cv=5,scoring='neg_mean_absolute_error')
            scores_rmse = cross_val_score(model_output, self.train_features, self.train_response, cv=5,scoring='neg_root_mean_squared_error')
            self.mse[model_output] = -1.0 * np.mean(scores_mse)
            self.mae[model_output] = -1.0 * np.mean(scores_mae)
            self.rmse[model_output] = -1.0 * np.mean(scores_rmse)
    # picking the model with the least CV RMSE, then fitting and predicting that model
    def get_best_model(self):
        '''Selecting best model with RMSE, fitting the model train data'''
        self.best_model = min(self.rmse, key=self.rmse.get)
        self.get_model_performance()
    def get_model_performance(self):
        print("Model Performance")
        for key, item in self.rmse.items():
            print('\n Score of the model {} :-'.format(key))
            print('\n RMSE - {}'.format(item))
        print('\n Best model with smallest RMSE\n\n {} :-'.format(self.best_model))
        print('\n RMSE - {}'.format(self.rmse[self.best_model]))
        print('\nTraining the Best Model.....')
        self.best_model.fit(self.train_features, self.train_response)
        print('\n Getting Feature Importance')
        self._plot_feature_importance()
        print('\nPrediction for test data with Best Model')
        self.testDf[self.pred_response] = self.best_model.predict(self.testDf)
        
        print('-------------------------- Best Model Performance ------------------------')
        print(self.testDf[self.pred_response])
    def _plot_feature_importance(self):
        '''Printing the feature importance used to train the model'''
        print('\n Feature Importance Calculation')
        features = self.train_features.columns.to_list()
        importances = self.best_model.feature_importances_
        indices = np.argsort(importances)
        plt.figure(figsize=(7, 6))
        plt.title('Feature Importances')
        plt.barh(range(len(indices)),
                 importances[indices], color='r', align='center')
        plt.yticks(range(len(indices)), [features[i] for i in indices])
        plt.xlabel('Relative Importance')
        plt.show()
        
    @staticmethod
    def saving_best_model(model_file, model):
        ''' Saving the best model to a file'''
        print('\n Saving Best Model to file')
        pickle.dump(model, open(model_file, 'wb'))
    print('Saving the Predictions to CSV file')
    def saving_results(self, sub_file, df):
        print('\n Saving job Salary predictions in testDf to a CSV file')
        print('--------------------------------------------------------------------------------')
        self.testDf[self.pred_response].to_csv(sub_file, index=True, header = 0)
    @staticmethod
    def hyperparameter_tuning(estimator, param_grid, n_iter=5, scoring='neg_root_mean_absolute_error', cv=5, n_jobs=-2,
                              refit=False):
        ''' Finding Optimal hyper-parameters used in models'''
        rs_cv = RandomizedSearchCV(estimator=estimator, param_distribution=param_grid,
                                   n_iter=n_iter,
                                   cv=cv,
                                   n_jobs=n_jobs,
                                   refit=refit)
        rs_cv.fit(train_features, train_response)
        return (rs_cv.best_params_)

6. Mengevaluasi Model Pembelajaran Mesin Kami

Saya menggunakan teknik pengambilan sampel ulang K-Fold Cross Validation untuk memperkirakan RMSE yang akan dicapai model saya pada kumpulan data pengujian. Ini adalah rata-rata RMSE yang kami peroleh saat melatih model sebanyak K kali, dan setiap kali, data lipatan ke-K digunakan sebagai proksi untuk data pengujian.

Model dilatih menggunakan K-fold cross-validation menggunakan K=5 untuk alasan kesederhanaan. Fitur pelatihan telah digunakan sebagai kumpulan variabel eksplorasi (X_train) untuk mempelajari dan menyesuaikan model, bersama dengan gaji sebagai variabel dependen (Y_train). Banyak model telah dilatih dengan cara ini. Kemudian CV RMSE mereka diperkirakan untuk membandingkan semua model.

CV RMSE untuk setiap model ini telah digunakan untuk memperbarui model terbaik dengan membandingkan model terbaik saat ini dengan RMSE model baru dan memilih model dengan RMSE CV terkecil. Kemudian model terbaik yaitu GBM yang dipasang pada fitur pelatihan digunakan untuk memprediksi gaji (Y_test) menggunakan Fitur Data Uji (X_test).

GBM pada akhirnya memiliki perkiraan RMSE terkecil, jadi ini adalah model pilihan yang saya gunakan agar sesuai dengan model dan memprediksi gaji data pengujian.

Masalah selama Pelatihan

1: JobID tidak dapat digunakan sebagai fitur karena bersifat unik per observasi. Ada beberapa cara untuk mengatasi masalah ini, namun cara termudah untuk mengatasinya adalah dengan mengonversi id pekerjaan ke indeks untuk setiap bingkai data sehingga dapat disimpan bersama dengan gaji yang diperlukan dalam file akhir.

2: waktu yang dibutuhkan model untuk berlatih. Dalam hal ini, PySpark bisa menjadi pilihan yang lebih baik untuk melatih model dengan jutaan observasi, dan jika fiturnya lebih banyak, prosesnya akan lebih memakan waktu.

3: asumsi yang harus saya buat:

  • Saya berasumsi bahwa gaji untuk pekerjaan yang membutuhkan banyak pengalaman tidak boleh sama dengan 0, dan hal ini tampaknya tidak logis bagi saya. Oleh karena itu saya harus menghapusnya
  • Saya juga berasumsi bahwa gaji yang sangat besar memang masuk akal dan harus tetap ada dalam data karena berhubungan dengan posisi manajerial
  • K di K-fold CV yang saya biarkan menjadi default K= 5, tapi idealnya saya ingin menggunakan metode Elbow untuk ini.
  • Saya membuat asumsi terkait jumlah iterasi saat melatih model, yang saya pilih cukup besar (60) untuk memastikan akurasi model cukup baik.
  • Saya berasumsi bahwa K-fold CV RMSE adalah perkiraan yang tepat untuk pengujian RMSE karena selama setiap pelatihan ke-K, lipatan K-1 digunakan sebagai set pelatihan, dan lipatan ke-K digunakan sebagai proksi untuk set pengujian ke memperoleh RMSE, maka rata-rata di atas K RMSE ini, akan menjadi perkiraan yang baik untuk pengujian RMSE.

Selain RMSE, saya juga memperkirakan MSE dan MAE, yang juga merupakan metrik alternatif selain RMSE. Semua ukuran ini adalah metrik yang dapat digunakan untuk menilai performa model jenis regresi, seperti dalam kasus kami.

Jika Regresi Linier adalah model yang dipilih, kita juga dapat menggunakan R-squared atau Adjusted R-squared untuk menilai keakuratan model dan seberapa besar model tersebut menjelaskan gaji. Kami kemudian juga dapat melihat Kesalahan Standar dan lebar Interval Keyakinan fitur untuk membuat kesimpulan.

7. Pentingnya Fitur

“Jenis Pekerjaan” tampaknya memiliki dampak terbesar pada Gaji. Fitur lain yang berdampak signifikan terhadap gaji adalah Pengalaman dan jarak dari Metropolis. Id perusahaan dan gelar tampaknya merupakan fitur paling tidak penting yang tidak banyak membantu kita dalam menjelaskan variasi Gaji.

Saya telah mengidentifikasi fitur yang paling signifikan dan paling tidak signifikan dengan memplot grafik Kepentingan Fitur, di mana kepentingan fitur dihitung sebagai mean dan deviasi standar akumulasi RSS (Residual Sum of Squared) yang menurun dalam setiap pohon. Fitur yang paling signifikan ada di bagian atas, sesuai dengan batang terbesar, sedangkan fitur yang paling tidak signifikan ada di bagian bawah plot ini dengan batang terpendek.

Repositori GitHub dengan Kumpulan Data dan Kode Python di sini

Jika Anda menyukai artikel ini, berikut beberapa artikel lain yang mungkin Anda sukai:











Terima kasih sudah membaca

Saya mendorong Anda untuk "bergabung dengan Medium"agar memilikiakses penuh ke semua artikel saya tentang Ilmu Data, Pembelajaran Mesin, AI, dan topik lainnya.

Ikuti saya di "Medium"untuk membaca lebih banyak artikel tentang berbagai topik Ilmu Data dan Analisis Data. Untuk penerapan langsung konsep Pembelajaran Mesin, Matematika, dan Statistik, lihat akun Githubsaya.
Saya menyambut masukan dan dapat dihubungi di LinkedIn.

Selamat belajar!