全球约有4.5亿人患有心理障碍,包括焦虑和抑郁,这些可能是全球健康不良、压力和残疾的主要原因之一。随着居家办公的普及,这一问题变得更加严重。如果拥有适当的数据,可以预测某人是否具有高心理疲劳得分,然后组织可以采取适当的纠正措施来帮助该员工。
心理疲劳得分可以被建模为0-1之间的数值,由于这些是连续值,将使用机器学习回归器来预测这个值。根据数据集和需求,这个问题可以通过多种技术解决,如线性回归、Lasso和Ridge。不会详细介绍这些策略,因为将详细讨论如何使用CatBoost回归器来解决这个问题及其实现细节。
CatBoost因其高度准确的模型构建、出色的GPU或CPU训练速度、使用默认参数的卓越结果、对分类变量的良好处理(如名称所示)以及无需预处理(如独热编码)而受到青睐。它还提供了酷炫的可视化功能,如特征重要性和训练过程可视化,并且使用Python包非常简单。
将使用以下方法来解决这个回归问题,使用CatBoost回归器。让更详细地看看每个步骤的实现细节。
可以使用以下命令安装CatBoost:
pip install catboost
由于CatBoost具有一些酷炫的可视化功能,需要安装可视化软件,然后使用以下命令启用扩展:
# Install Package
pip install ipywidgets
# Turn on extension
jupyter nbextension enable --py widgetsnbextension
安装完包之后,将开始导入所需的库:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from catboost import CatBoostRegressor
import math
让为这个问题加载数据集。加载完成后,将查看前五行,并尝试弄清楚数据集的内容。可以使用以下代码来完成这个操作:
# Loading dataset from CSV file
df = pd.read_csv("train.csv", sep=",")
# Let's look at shape and first 5 rows of dataset
print("shape of dataframe is : ", df.shape)
df.head()
数据集包含数值和分类列。总共有22750个数据点和12个特征。
现在已经掌握了数据集,让看看是否有任何空值,以及每个列中空值的百分比。
# Checking null value percentage column wise
df.isnull().mean()*100
可以看到没有空值。因此,可以进行下一步。
数据清洗后,探索性数据分析是一个关键阶段。由于专注于如何实现CatBoost,这里不展示这一部分。
数据清洗和EDA之后,特征工程是一个重要步骤。可以移除对模型构建不重要的特征,从现有特征创建新特征,并为分类特征创建虚拟变量。所有这些步骤都取决于问题陈述。对于问题,将执行以下步骤:
# function to find out total days
def create_days_count(data):
return (current_date - data["Date of Joining"])
# Converting date of joining column to pandas datetime format
df["Date of Joining"] = pd.to_datetime(df["Date of Joining"])
# get todays date time
current_date = pd.to_datetime('today')
# Creating new column days_count
df["days_count"] = df.apply(create_days_count, axis=1).dt.days
# We will drop employeeid and date of joining columns.
df.drop(["Employee ID","Date of Joining"],axis=1,inplace=True)
接下来,将数据分割为因变量(X)和自变量(y),将预测这些变量。
# creating independent variables as X and target/dependent variable as y
y = df.pop("Mental Fatigue Score")
X = df
然后,将X和y分割为训练集和测试集。让使用80%的数据集进行模型训练,20%作为测试数据集,以验证模型在未见数据上的表现,因为这个测试数据集将包括真实值。
# Let's split X and y using Train test split
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=42)
# get shape of train and test data
print("train data size:", X_train.shape)
print("test data size:", X_test.shape)
必须定义哪些特征是分类的。如果没有定义分类特征,CatBoost将把它们视为数值。
# List of categorical columns
categoricalcolumns = X.select_dtypes(include=["object"]).columns.tolist()
print("Names of categorical columns : ", categoricalcolumns)
# Get location of categorical columns
cat_features = [X.columns.get_loc(col) for col in categoricalcolumns]
print("Location of categorical columns : ", cat_features)
CatBoost中的Pool函数结合了自变量和因变量(X和y)以及分类特征。
# importing Pool
from catboost import Pool
# Creating pool object for train dataset. we give information of categorical features to parameter cat_features
train_data = Pool(data=X_train,
label=y_train,
cat_features=cat_features
)
# Creating pool object for test dataset
test_data = Pool(data=X_test,
label=y_test,
cat_features=cat_features
)
将使用默认参数构建一个CatBoost模型。
# build model
cat_model = CatBoostRegressor(loss_function='RMSE')
# Fit model
cat_model.fit(X_train, y_train,
eval_set=(X_test, y_test),
plot=True
)
使用plot=True并在fit模型时传递测试集到eval_set参数,可以看到模型学习情况的酷炫图表,以及它是否开始过拟合。还可以在迭代过程中看到最佳结果的指标。
# Create a dataframe of feature importance
df_feature_importance = pd.DataFrame(cat_model.get_feature_importance(prettified=True))
# plotting feature importance
plt.figure(figsize=(12, 6));
feature_plot = sns.barplot(x="Importances", y="Feature Id", data=df_feature_importance, palette="cool");
plt.title('features importance');
将使用以下代码找到测试数据集上的均方根误差、R2分数和调整后的R2分数。
y_predict = cat_model.predict(X_test)
# RMSE
Rmse_test = math.sqrt(mean_squared_error(y_test, y_predict))
# R2 Score
r2_test = r2_score(y_test, y_predict)
# Adjusted R2 Score
n = X_train.shape[0] # total no of datapoints
p = X_train.shape[1] # total no of independent features
adj_r2_test = 1 - (1 - r2_test) * (n - 1) / (n - p - 1)
# print results
print("Evaluation on test data")
print("RMSE: {:.2f}".format(Rmse_test))
print("R2: {:.2f}".format(r2_test))
print("Adjusted R2: {:.2f}".format(adj_r2_test))