★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>

1.背景描述

本数据集来自全球校内学生健康调查(GSHS)是一项以学校为基础的调查,调查使用自填式问卷来获取年轻人的健康行为和与发病和死亡的主要原因有关的保护因素的数据。
该调查于2018年在阿根廷进行。共有56,981名学生参加。
学校回复率为86%,学生回复率为74%,总体回复率为63%。

2.数据说明

字段说明
Bullied on school property in past 12 months,在过去的12个月里,在学校范围内受到霸凌
Bullied not on school property in past 12_months在过去的12个月里,在学校以外的地方受到过霸凌
Cyber bullied in past 12 months过去12个月内被网络霸凌的情况
Custom Age自定义年龄
Sex性别
Physically attacked身体受到攻击
Physical fighting身体对抗
Felt lonely感到孤独
Close friends亲密的朋友
Miss school no permission未经学校许可的缺勤天数
Other students kind and helpful其他学生的善意和帮助
Parents understand problems父母是否知情
Most of the time or always felt lonely大部分时间或总是感到孤独
Missed classes or school without permission未经允许而缺课或旷课
Were underweight是否体重过轻
Were overweight是否体重过重
Were obese是否肥胖

3.问题描述

通常,霸凌与孤独感、缺乏亲密朋友、与父母沟通不畅、缺课等有关。(例如,Nansel等人在美国青年中的欺凌行为:普遍性和与社会心理适应的联系)。调查数据显示,被霸凌者多为体重不足、超重和肥胖的人。

二、数据处理

1.读取数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px

import os
df = pd.read_csv("data/data208695/Bullying_Dataset.csv",sep=',')
df.head()
序号过去12个月内受到校内霸凌过去12个月内校外受到霸凌过去12个月内受到网络霸凌年龄性别身体受到攻击身体对抗感到孤独亲密的朋友未经学校许可的缺勤天数其他学生的善意和帮助父母了解问题大部分时间或总是感到孤独未经允许而缺课或旷课体重过轻体重过重肥胖
01YesYes13Female0 times0 timesAlways210 or more daysNeverAlwaysYesYes
12NoNoNo13Female0 times0 timesNever3 or more0 daysSometimesAlwaysNoNo
23NoNoNo14Male0 times0 timesNever3 or more0 daysSometimesAlwaysNoNoNoNoNo
34NoNoNo16Male0 times2 or 3 timesNever3 or more0 daysSometimesNoNoNoNoNo
45NoNoNo13Female0 times0 timesRarely3 or more0 daysMost of the timeMost of the timeNoNo
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 56981 entries, 0 to 56980
Data columns (total 18 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   序号             56981 non-null  int64 
 1   过去12个月内受到校内霸凌  56981 non-null  object
 2   过去12个月内校外受到霸凌  56981 non-null  object
 3   过去12个月内受到网络霸凌  56981 non-null  object
 4   年龄             56981 non-null  object
 5   性别             56981 non-null  object
 6   身体受到攻击         56981 non-null  object
 7   身体对抗           56981 non-null  object
 8   感到孤独           56981 non-null  object
 9   亲密的朋友          56981 non-null  object
 10  未经学校许可的缺勤天数    56981 non-null  object
 11  其他学生的善意和帮助     56981 non-null  object
 12  父母了解问题         56981 non-null  object
 13  大部分时间或总是感到孤独   56981 non-null  object
 14  未经允许而缺课或旷课     56981 non-null  object
 15  体重过轻           56981 non-null  object
 16  体重过重           56981 non-null  object
 17  肥胖             56981 non-null  object
dtypes: int64(1), object(17)
memory usage: 7.8+ MB

2.统计空值

对于内容为空白的,替换为空值

df.replace(r'^\s*$', np.nan, regex=True, inplace=True)
  • ^ 代表开始
  • $ 代表结束
  • \s 空白字符
    • 代表多次
df.replace(r'^\s*$', np.nan, regex=True, inplace=True)
df.isnull().sum()
序号                   0
过去12个月内受到校内霸凌     1239
过去12个月内校外受到霸凌      489
过去12个月内受到网络霸凌      571
年龄                 108
性别                 536
身体受到攻击             240
身体对抗               268
感到孤独               366
亲密的朋友             1076
未经学校许可的缺勤天数       1864
其他学生的善意和帮助        1559
父母了解问题            2373
大部分时间或总是感到孤独       366
未经允许而缺课或旷课        1864
体重过轻             20929
体重过重             20929
肥胖               20929
dtype: int64

体重过轻 、体重过重、肥胖 这几类空值很多,可以不用算在特整理。

3.缺失值可视化

主要是中文显示,aistudio目前内置了中文字题,需要特别声明。

import warnings
warnings.filterwarnings("ignore")

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
%matplotlib inline

# 设置显示中文
matplotlib.rcParams['font.sans-serif'] = ['FZSongYi-Z13S'] # 指定默认字体
matplotlib.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题

# 各列缺失值百分比
missing_perc = (df.isnull().sum() / len(df)) * 100

# 降序排列
missing_perc_sorted = missing_perc.sort_values(ascending=False)

# 计算缺失值的累积百分比
cumulative_perc = missing_perc_sorted.cumsum()

# 制作一个帕累托图表
fig, ax1 = plt.subplots(figsize=(10, 6))
ax1.bar(missing_perc_sorted.index, missing_perc_sorted.values, color='tab:blue')
ax1.set_xlabel('特征')
ax1.set_ylabel('缺失值比例', color='tab:blue')
ax1.set_xticklabels(missing_perc_sorted.index, rotation=90)

# 为累积百分比添加第二个y轴
ax2 = ax1.twinx()
ax2.plot(missing_perc_sorted.index, cumulative_perc.values, color='tab:red', marker='o')
ax2.set_ylabel('累积百分数', color='tab:red')


# 旋转x轴标签以便更好地显示
plt.xticks(rotation=90)

# 显示
plt.show()

在这里插入图片描述

4.删除缺失值较多的 特征列

# Drop columns with a high proportion of missing values
df.drop(['肥胖', '体重过轻', '体重过重'], axis=1, inplace=True)

#dropping na values
df=df.dropna()

5.空值检查

# 各列非空值统计
non_null_counts = df.count()

# 检查是否所有列都有相同的非空值计数
if non_null_counts.nunique() == 1:
    print("Total null values:", df.isnull().sum().sum())
else:
    print("Columns have different counts of non-null values.")
Total null values: 0
df.head()
序号过去12个月内受到校内霸凌过去12个月内校外受到霸凌过去12个月内受到网络霸凌年龄性别身体受到攻击身体对抗感到孤独亲密的朋友未经学校许可的缺勤天数其他学生的善意和帮助父母了解问题大部分时间或总是感到孤独未经允许而缺课或旷课
12NoNoNo13Female0 times0 timesNever3 or more0 daysSometimesAlwaysNoNo
23NoNoNo14Male0 times0 timesNever3 or more0 daysSometimesAlwaysNoNo
45NoNoNo13Female0 times0 timesRarely3 or more0 daysMost of the timeMost of the timeNoNo
56NoNoNo13Male0 times1 timeNever3 or more0 daysMost of the timeAlwaysNoNo
67NoNoNo14Female1 time0 timesSometimes3 or more0 daysMost of the timeAlwaysNoNo
df.head()
序号过去12个月内受到校内霸凌过去12个月内校外受到霸凌过去12个月内受到网络霸凌年龄性别身体受到攻击身体对抗感到孤独亲密的朋友未经学校许可的缺勤天数其他学生的善意和帮助父母了解问题大部分时间或总是感到孤独未经允许而缺课或旷课
12NoNoNo13Female0 times0 timesNever3 or more0 daysSometimesAlwaysNoNo
23NoNoNo14Male0 times0 timesNever3 or more0 daysSometimesAlwaysNoNo
45NoNoNo13Female0 times0 timesRarely3 or more0 daysMost of the timeMost of the timeNoNo
56NoNoNo13Male0 times1 timeNever3 or more0 daysMost of the timeAlwaysNoNo
67NoNoNo14Female1 time0 timesSometimes3 or more0 daysMost of the timeAlwaysNoNo

三、特征处理

1.特征分类变量序列化

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
# 除去序号列
columns=df.columns[1:]
print(len(columns))
for column in columns:
    print(column)
14
过去12个月内受到校内霸凌
过去12个月内校外受到霸凌
过去12个月内受到网络霸凌
年龄
性别
身体受到攻击
身体对抗
感到孤独
亲密的朋友
未经学校许可的缺勤天数
其他学生的善意和帮助
父母了解问题
大部分时间或总是感到孤独
未经允许而缺课或旷课
for column in columns:
    print(f"完成 {column} 列序列化")
    df[column]=le.fit_transform(df[column])
完成 过去12个月内受到校内霸凌 列序列化
完成 过去12个月内校外受到霸凌 列序列化
完成 过去12个月内受到网络霸凌 列序列化
完成 年龄 列序列化
完成 性别 列序列化
完成 身体受到攻击 列序列化
完成 身体对抗 列序列化
完成 感到孤独 列序列化
完成 亲密的朋友 列序列化
完成 未经学校许可的缺勤天数 列序列化
完成 其他学生的善意和帮助 列序列化
完成 父母了解问题 列序列化
完成 大部分时间或总是感到孤独 列序列化
完成 未经允许而缺课或旷课 列序列化
df.head()
序号过去12个月内受到校内霸凌过去12个月内校外受到霸凌过去12个月内受到网络霸凌年龄性别身体受到攻击身体对抗感到孤独亲密的朋友未经学校许可的缺勤天数其他学生的善意和帮助父母了解问题大部分时间或总是感到孤独未经允许而缺课或旷课
1200020002304000
2300031002304000
4500020003301100
5600021012301000
6700030104301000

2.数据集切分

from sklearn.model_selection import train_test_split

# 切分数据集为 训练集 、 测试集
X = df.drop(['序号', '身体受到攻击'], axis=1)
y = df['身体受到攻击']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2023)

四、模型训练

!pip install catboost

1.决策树预测 Decision Tree Classifier

import xgboost
import lightgbm
from sklearn.svm import SVC
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from catboost import CatBoostClassifier
# 训练决策树分类器
clf = DecisionTreeClassifier(random_state=1024)
clf.fit(X_train, y_train)
accuracy_list = []
# test数据集预测
y_pred = clf.predict(X_test)
from sklearn.metrics import accuracy_score

# 评估精度
accuracy = accuracy_score(y_test, y_pred)
print("精度: %.4f%%" % (accuracy * 100.0))
accuracy_list.append(accuracy*100)
精度: 76.2585%

2.随机森林 RandomForestClassifier

from sklearn.ensemble import RandomForestClassifier


r_clf = RandomForestClassifier(max_features=0.5, max_depth=15, random_state=1)
r_clf.fit(X_train, y_train)
r_pred = r_clf.predict(X_test)
r_acc = accuracy_score(y_test, r_pred)
print(r_acc)
accuracy_list.append(100*r_acc)
0.8279972416510688

3.逻辑回归Logistic Regression

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
log_reg_pred = log_reg.predict(X_test)
log_reg_acc = accuracy_score(y_test, log_reg_pred)
print(log_reg_acc)
accuracy_list.append(100*log_reg_acc)
0.8344990641316127

4.支持向量机Support Vector

sv_clf = SVC()
sv_clf.fit(X_train, y_train)
sv_clf_pred = sv_clf.predict(X_test)
sv_clf_acc = accuracy_score(y_test, sv_clf_pred)
print(sv_clf_acc)
accuracy_list.append(100* sv_clf_acc)
0.8360752635208354

5.K临近算法K Neighbors Classifier

kn_clf = KNeighborsClassifier(n_neighbors=6)
kn_clf.fit(X_train, y_train)
kn_pred = kn_clf.predict(X_test)
kn_acc = accuracy_score(y_test, kn_pred)
print(kn_acc)
accuracy_list.append(100*kn_acc)
0.8304600531967293

6.梯度增强分类器 Gradient Boosting Classifier

gradientboost_clf = GradientBoostingClassifier(max_depth=2, random_state=1)
gradientboost_clf.fit(X_train,y_train)
gradientboost_pred = gradientboost_clf.predict(X_test)
gradientboost_acc = accuracy_score(y_test, gradientboost_pred)
print(gradientboost_acc)
accuracy_list.append(100*gradientboost_acc)
0.8364693133681411

6.xgbrf分类器 xgbrf classifier

xgb_clf = xgboost.XGBRFClassifier(max_depth=3, random_state=1)
xgb_clf.fit(X_train,y_train)
xgb_pred = xgb_clf.predict(X_test)
xgb_acc = accuracy_score(y_test, xgb_pred)
accuracy_list.append(100*xgb_acc)
print(xgb_acc)
[23:09:17] WARNING: ../src/learner.cc:1061: Starting in XGBoost 1.3.0, the default evaluation metric used with the objective 'multi:softprob' was changed from 'merror' to 'mlogloss'. Explicitly set eval_metric if you'd like to restore the old behavior.
0.8360752635208354

7.LGBMClassifier

lgb_clf = lightgbm.LGBMClassifier(max_depth=2, random_state=4)
lgb_clf.fit(X_train,y_train)
lgb_pred = lgb_clf.predict(X_test)
lgb_acc = accuracy_score(y_test, lgb_pred)
print(lgb_acc)
accuracy_list.append(100*lgb_acc)
0.8363708009063147

8.Cat Boost Classifier

cat_clf = CatBoostClassifier()
cat_clf.fit(X_train,y_train)
cat_pred = cat_clf.predict(X_test)
cat_acc = accuracy_score(y_test, cat_pred)
print(cat_acc)
accuracy_list.append(100*cat_acc)
990:	learn: 0.4190779	total: 12.3s	remaining: 112ms
991:	learn: 0.4189944	total: 12.3s	remaining: 99.5ms
992:	learn: 0.4189137	total: 12.3s	remaining: 87ms
993:	learn: 0.4188195	total: 12.4s	remaining: 74.6ms
994:	learn: 0.4187774	total: 12.4s	remaining: 62.2ms
995:	learn: 0.4187095	total: 12.4s	remaining: 49.7ms
996:	learn: 0.4186093	total: 12.4s	remaining: 37.3ms
997:	learn: 0.4185544	total: 12.4s	remaining: 24.9ms
998:	learn: 0.4184855	total: 12.4s	remaining: 12.4ms
999:	learn: 0.4183650	total: 12.4s	remaining: 0us
0.8307555905822086

五、各模型结果对比

print(accuracy_list)
[76.25849669983253, 82.79972416510688, 83.44990641316127, 83.60752635208354, 83.04600531967293, 83.6469313368141, 83.60752635208354, 83.63708009063147, 83.07555905822086]

368141, 83.60752635208354, 83.63708009063147, 83.07555905822086]

model_list = ['DecisionTree', 'RandomForest', 'Logistic Regression', 'SVC','KNearestNeighbours',  
              'GradientBooster', 'XGBRF','LGBM', 'CatBoostClassifier']
plt.rcParams['figure.figsize']=20,8
sns.set_style('darkgrid')
ax = sns.barplot(x=model_list, y=accuracy_list, palette = "husl", saturation =2.0)
plt.xlabel('Classifier Models', fontsize = 20 )
plt.ylabel('% of Accuracy', fontsize = 20)
plt.title('Accuracy of different Classifier Models', fontsize = 20)
plt.xticks(fontsize = 12, horizontalalignment = 'center', rotation = 8)
plt.yticks(fontsize = 12)
for i in ax.patches:
    width, height = i.get_width(), i.get_height()
    x, y = i.get_xy() 
    ax.annotate(f'{round(height,2)}%', (x + width/2, y + height*1.02), ha='center', fontsize = 'x-large')
plt.show()

SVC支持向量机、xgbrf 、lightgbm 耗时特别长,以后不用它!

此文章为搬运
原项目链接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐