哈喽,我是Johngo~
拿到了一位同学,前两天面试腾讯的一个面试内容。岗位是机器学习算法岗。
然后对其中的核心内容进行了整理。
大家可以看看~
在不平衡数据集中,某些类别的样本数量远多于其他类别,这会导致模型更倾向于预测多数类,而忽略少数类。
列举几种方法~
这是最直接的方法,包括上采样(增加少数类样本)和下采样(减少多数类样本)。
可以使用 RandomOverSampler
或 SMOTE
(Synthetic Minority Over-sampling Technique)来增加少数类样本数量。
from imblearn.over_sampling import RandomOverSampler, SMOTE
from collections import Counter
import pandas as pd
# 假设我们有一个数据集 df 和标签 y
# df = ...
# y = ...
# 使用随机过采样
ros = RandomOverSampler(random_state=42)
X_res, y_res = ros.fit_resample(df, y)
print('Random over-sampled dataset shape %s' % Counter(y_res))
# 使用SMOTE
smote = SMOTE(random_state=42)
X_smote, y_smote = smote.fit_resample(df, y)
print('SMOTE dataset shape %s' % Counter(y_smote))
可以使用 RandomUnderSampler
来减少多数类样本数量。
from imblearn.under_sampling import RandomUnderSampler
# 使用随机下采样
rus = RandomUnderSampler(random_state=42)
X_res, y_res = rus.fit_resample(df, y)
print('Random under-sampled dataset shape %s' % Counter(y_res))
由于准确率在不平衡数据集上可能误导,可以考虑使用其他评价指标,如 F1-score、AUC-ROC、精确率(Precision)和召回率(Recall)。
from sklearn.metrics import classification_report, roc_auc_score
# 假设我们有一个模型 model
# model.fit(X_train, y_train)
# y_pred = model.predict(X_test)
# y_prob = model.predict_proba(X_test)[:, 1]
# 打印分类报告
print(classification_report(y_test, y_pred))
# 计算并打印AUC-ROC
auc_roc = roc_auc_score(y_test, y_prob)
print(f'AUC-ROC: {auc_roc}')
一些模型能够处理不平衡数据集,比如 XGBoost、LightGBM 等,它们可以通过参数调整来增加对少数类样本的关注。
import xgboost as xgb
# 使用XGBoost并设置scale_pos_weight参数
model = xgb.XGBClassifier(scale_pos_weight=ratio)
model.fit(X_train, y_train)
# 预测并评价
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred))
使用集成学习方法如 Bagging 和 Boosting,可以提升模型对不平衡数据集的表现。
from sklearn.ensemble import BaggingClassifier, AdaBoostClassifier
# 使用Bagging
bagging = BaggingClassifier(base_estimator=model, n_estimators=10, random_state=42)
bagging.fit(X_train, y_train)
y_pred = bagging.predict(X_test)
print(classification_report(y_test, y_pred))
# 使用AdaBoost
adaboost = AdaBoostClassifier(base_estimator=model, n_estimators=10, random_state=42)
adaboost.fit(X_train, y_train)
y_pred = adaboost.predict(X_test)
print(classification_report(y_test, y_pred))
通过数据增强技术,可以生成更多样的少数类样本。
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# 假设X_train是图像数据,y_train是标签
datagen.fit(X_train)
1. 选择合适的方法:不同方法对不同数据集的效果不同,可能需要实验几种方法来找到最佳解决方案。2. 保持数据的原始特性:在处理数据时,尽量不要破坏数据的原始特性,尤其是在使用采样方法时。 3. 合理评估模型:使用多个评价指标综合评估模型的表现,避免依赖单一指标。
上述方法,可以有效处理不平衡数据集,提升模型对少数类样本的预测能力。
ROC曲线 是一种用于评估二分类模型性能的图形化工具。
它以真阳率 TPR 为纵轴,FPR 为横轴绘制曲线。TPR是指在实际为正例的样本中,被模型正确预测为正例的比例,计算公式为:TPR = TP / (TP + FN),其中TP是真正例数量,FN是假负例数量。而FPR则是指在实际为负例的样本中,被模型错误预测为正例的比例,计算公式为:FPR = FP / (FP + TN),其中FP是假正例数量,TN是真负例数量。
ROC曲线的绘制过程是:首先,将分类器的输出按照预测为正例的概率从高到低排序,然后逐个将阈值设为各个概率值,计算对应的TPR和FPR,以这些点为坐标绘制曲线。ROC曲线的一般特点是,曲线越靠近左上角,分类器性能越好,因为这意味着TPR较高而FPR较低。
AUC(Area Under the Curve)是ROC曲线下的面积,用于量化分类器性能的一个指标。AUC的取值范围在0到1之间,完美分类器的AUC为1,随机分类器的AUC为0.5。AUC越接近1,表示分类器性能越好,AUC越接近0.5,则表示分类器的性能越接近随机。
在实际应用中,ROC曲线和AUC常用于比较不同分类器的性能、选择最佳的分类器、调节分类器的阈值等。
需要注意的是,当样本不平衡时,AUC仍然是一个有效的评估指标,因为AUC的计算不受样本分布的影响。
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
# 以某个分类器的预测概率和真实标签为例
# y_score为分类器的预测概率,y_true为真实标签(0或1)
fpr, tpr, thresholds = roc_curve(y_true, y_score)
# 计算AUC
roc_auc = auc(fpr, tpr)
# 绘制ROC曲线
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()
在这段代码中,roc_curve
函数计算了给定真实标签和预测概率下的FPR和TPR,然后通过auc
函数计算了AUC值。最后,使用Matplotlib绘制了ROC曲线。
交叉验证是一种用于评估机器学习模型性能和选择最佳模型的方法。
通过将数据集分成多个子集,然后重复使用这些子集来训练和测试模型,从而有效地利用了可用的数据。交叉验证有助于减少由于数据划分不合理而引入的偏差,提高了模型评估的可靠性。
常见的交叉验证方法包括k折交叉验证和留一交叉验证。在k折交叉验证中,数据集被均匀分成k个子集,每次使用其中一个子集作为验证集,剩余的k-1个子集作为训练集,重复k次,每次选取不同的验证集。而留一交叉验证是k折交叉验证的一种特殊情况,其中k等于数据集的样本数量,每个样本依次作为验证集,其余样本作为训练集。
交叉验证的步骤如下:
使用交叉验证可以帮助我们更好地了解模型的泛化能力,因为它在多个数据集上进行评估,而不仅仅是在单个数据集上。这有助于减少过拟合和选择具有较好泛化能力的模型。
实现k折交叉验证:
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 创建模型
model = LogisticRegression()
# 使用k折交叉验证评估模型
scores = cross_val_score(model, X, y, cv=5) # cv表示折数,这里是5折交叉验证
# 输出交叉验证得分
print("交叉验证得分:", scores)
print("平均交叉验证得分:", scores.mean())
使用了逻辑回归模型,将数据集分成5折进行交叉验证,并计算了每折的得分以及平均得分。
处理缺失值是数据预处理中的重要步骤之一,因为缺失值会对模型训练和预测产生不良影响。通常情况下,我们需要使用合适的方法来填充或处理缺失值,以确保数据的完整性和准确性。
下面是处理缺失值的一些常见方法:
1. 删除缺失值: 如果数据集中的某些样本的特征存在大量缺失值,且这些特征对于模型训练没有太大的影响,那么可以考虑删除这些样本或特征。但是要注意,删除数据可能会导致信息丢失,从而影响模型的性能。
2. 填充缺失值:
3. 特殊值标记: 将缺失值用特殊的标记值(如-1、999等)替换,以便后续模型可以识别这些缺失值并进行处理。
4. 使用专门的缺失值处理算法: 有些机器学习算法对缺失值有一定的容忍度,如决策树和随机森林。对于这些算法,可以直接在模型中处理缺失值。
在实验中,选择哪种方法处理缺失值取决于数据的特点、缺失值的分布情况以及模型的需求。需要注意的是,在处理缺失值时,要注意不要破坏原始数据的分布特征,并且要避免引入过多的人为偏差。
处理缺失值:
import pandas as pd
# 创建包含缺失值的示例数据
data = {'A': [1, 2, None, 4],
'B': [5, None, 7, 8],
'C': [None, 10, 11, 12]}
df = pd.DataFrame(data)
# 查看数据集中的缺失值
print("原始数据集:")
print(df)
# 填充缺失值为均值
df_filled = df.fillna(df.mean())
# 删除包含缺失值的行
df_dropped = df.dropna()
print("\n填充缺失值后的数据集:")
print(df_filled)
print("\n删除缺失值后的数据集:")
print(df_dropped)
上面代码中,使用Pandas库中的fillna
方法将缺失值填充为均值,并使用dropna
方法删除包含缺失值的行。
特征选择是要从原始特征集中选择最具有代表性的特征,以提高模型的性能和泛化能力,同时减少模型的复杂度。
下面是一些常见的特征选择方法,包括L1正则化和基于树的方法:
1. 过滤式特征选择(Filter Method): 这种方法先对特征进行评估或打分,然后根据评分选择特征。常用的评估指标包括信息增益、方差、相关系数等。过滤式特征选择与具体的机器学习模型无关,可以独立于模型进行特征选择。
2. 包裹式特征选择(Wrapper Method): 这种方法直接使用机器学习模型对不同的特征子集进行训练和评估,并选择性能最好的特征子集。常见的包裹式特征选择算法有递归特征消除(Recursive Feature Elimination,RFE)和正向选择(Forward Selection)等。
3. 嵌入式特征选择(Embedded Method): 这种方法将特征选择过程与模型训练过程结合在一起,通过在模型训练过程中自动选择最佳的特征子集来提高模型性能。常见的嵌入式特征选择方法包括L1正则化和基于树的方法。
在实际应用中,特征选择的方法需要根据具体的数据集和机器学习任务进行选择。有时候需要尝试多种方法来确定最佳的特征子集。下面是使用Python中的Scikit-learn库进行L1正则化和基于树的特征选择的示例代码:
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
from sklearn.preprocessing import StandardScaler
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 特征标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 使用L1正则化进行特征选择
logistic = LogisticRegression(penalty='l1', solver='liblinear', random_state=42)
logistic.fit(X_scaled, y)
selected_features_idx = logistic.coef_ != 0
# 输出选择的特征
selected_features = iris.feature_names[selected_features_idx[0]]
print("L1正则化选择的特征:", selected_features)
# 使用基于树的特征选择方法
forest = RandomForestClassifier(n_estimators=100, random_state=42)
forest.fit(X, y)
feature_importances = forest.feature_importances_
# 基于特征重要性选择特征
model = SelectFromModel(forest, prefit=True)
X_selected = model.transform(X)
# 输出选择的特征
selected_features_idx = model.get_support(indices=True)
selected_features = iris.feature_names[selected_features_idx]
print("基于树的特征选择方法选择的特征:", selected_features)
整体的代码中,首先使用L1正则化进行特征选择,然后使用基于随机森林的特征重要性来选择特征。
特征缩放在机器学习中是一个重要的预处理步骤,其目的是将数据特征的范围缩放到相似的尺度,以确保不同特征对模型训练的影响权重相近。特征缩放通常用于那些特征的取值范围差异较大的情况下,以保证模型的稳定性和收敛性。常用的特征缩放方法包括标准化和归一化。
1. 标准化(Standardization): 标准化是一种常见的特征缩放方法,它将特征的取值缩放到均值为0、方差为1的标准正态分布。标准化的公式如下:
其中,
是原始特征值,
是特征的均值,
是特征的标准差。
标准化使得特征的分布更加接近标准正态分布,有利于某些机器学习算法的收敛速度,尤其是那些基于梯度的优化算法。
2. 归一化(Normalization): 归一化是将特征的取值范围缩放到
之间的过程,使得所有特征的取值都在同一尺度上。归一化的公式如下:
其中,
是特征的最小值,
是特征的最大值。
归一化适用于那些特征的取值范围不相同,但又需要保留原始数据分布和稀疏性的情况,例如图像像素的处理。
在实际应用中,可以根据数据的分布情况和模型的需求选择合适的特征缩放方法。以下是使用Python中的Scikit-learn库进行标准化和归一化的示例代码:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np
# 创建示例数据
data = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 标准化
scaler = StandardScaler()
data_standardized = scaler.fit_transform(data)
print("标准化后的数据:")
print(data_standardized)
# 归一化
scaler = MinMaxScaler()
data_normalized = scaler.fit_transform(data)
print("\n归一化后的数据:")
print(data_normalized)
代码中,首先使用StandardScaler
进行标准化,然后使用MinMaxScaler
进行归一化。