导航菜单

面试题与前沿

常见面试题

1. 数据预处理

数据预处理是数据挖掘的重要环节,面试中经常涉及相关问题。

# 常见问题

1. 如何处理缺失值?
   - 删除法:直接删除包含缺失值的样本
   - 均值/中位数填充:用统计量填充缺失值
   - 模型预测填充:使用机器学习模型预测缺失值
   - 多重插补:生成多个可能的填充值

2. 如何处理异常值?
   - 统计方法:Z-score、IQR法
   - 基于距离的方法:K近邻、马氏距离
   - 基于密度的方法:LOF、DBSCAN
   - 基于聚类的方法:K-means、层次聚类

3. 如何进行特征选择?
   - 过滤法:方差分析、相关性分析
   - 包装法:递归特征消除、前向选择
   - 嵌入法:Lasso正则化、决策树特征重要性

4. 如何处理类别特征?
   - 标签编码:将类别转换为整数
   - 独热编码:将类别转换为二进制向量
   - 目标编码:基于目标变量的统计量
   - 哈希编码:将类别映射到固定维度的向量

# 代码示例
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.feature_selection import SelectKBest, f_classif

# 1. 处理缺失值
def handle_missing_values(df, method='mean'):
    if method == 'mean':
        imputer = SimpleImputer(strategy='mean')
    elif method == 'median':
        imputer = SimpleImputer(strategy='median')
    elif method == 'most_frequent':
        imputer = SimpleImputer(strategy='most_frequent')
    else:
        raise ValueError("Invalid imputation method")
    
    return pd.DataFrame(
        imputer.fit_transform(df),
        columns=df.columns
    )

# 2. 处理异常值
def handle_outliers(df, column, method='zscore'):
    if method == 'zscore':
        mean = df[column].mean()
        std = df[column].std()
        df[column] = df[column].clip(
            lower=mean-3*std,
            upper=mean+3*std
        )
    elif method == 'iqr':
        Q1 = df[column].quantile(0.25)
        Q3 = df[column].quantile(0.75)
        IQR = Q3 - Q1
        df[column] = df[column].clip(
            lower=Q1-1.5*IQR,
            upper=Q3+1.5*IQR
        )
    else:
        raise ValueError("Invalid outlier handling method")
    
    return df

# 3. 特征选择
def select_features(X, y, k=10):
    selector = SelectKBest(f_classif, k=k)
    X_selected = selector.fit_transform(X, y)
    return X_selected, selector.get_support()

# 4. 类别特征编码
def encode_categorical_features(df, columns, method='onehot'):
    if method == 'onehot':
        return pd.get_dummies(df, columns=columns)
    elif method == 'label':
        from sklearn.preprocessing import LabelEncoder
        df_encoded = df.copy()
        for col in columns:
            le = LabelEncoder()
            df_encoded[col] = le.fit_transform(df[col])
        return df_encoded
    else:
        raise ValueError("Invalid encoding method")

2. 机器学习算法

机器学习算法是数据挖掘的核心,面试中经常考察算法原理和实现。

# 常见问题

1. 决策树算法原理?
   - 信息增益:选择信息增益最大的特征作为分裂点
   - 基尼指数:选择基尼指数最小的特征作为分裂点
   - 剪枝:预剪枝和后剪枝防止过拟合
   - 优点:可解释性强、处理非线性关系
   - 缺点:容易过拟合、对噪声敏感

2. 随机森林算法原理?
   - 集成学习:多个决策树的组合
   - 随机性:随机选择特征和样本
   - 投票机制:多数投票决定最终结果
   - 优点:抗过拟合、处理高维数据
   - 缺点:计算复杂度高、模型解释性差

3. SVM算法原理?
   - 最大间隔:寻找最优分类超平面
   - 核技巧:处理非线性分类问题
   - 软间隔:处理噪声和异常值
   - 优点:泛化能力强、处理高维数据
   - 缺点:计算复杂度高、对大规模数据不友好

4. 聚类算法原理?
   - K-means:基于距离的聚类
   - 层次聚类:自底向上或自顶向下
   - DBSCAN:基于密度的聚类
   - 优点:无监督学习、发现数据模式
   - 缺点:需要确定参数、对噪声敏感

# 代码示例
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.cluster import KMeans

# 1. 决策树
def decision_tree_example(X, y):
    model = DecisionTreeClassifier(
        max_depth=5,
        min_samples_split=10,
        random_state=42
    )
    model.fit(X, y)
    return model

# 2. 随机森林
def random_forest_example(X, y):
    model = RandomForestClassifier(
        n_estimators=100,
        max_depth=5,
        random_state=42
    )
    model.fit(X, y)
    return model

# 3. SVM
def svm_example(X, y):
    model = SVC(
        kernel='rbf',
        C=1.0,
        random_state=42
    )
    model.fit(X, y)
    return model

# 4. K-means
def kmeans_example(X, n_clusters=3):
    model = KMeans(
        n_clusters=n_clusters,
        random_state=42
    )
    model.fit(X)
    return model

3. 模型评估

模型评估是机器学习项目的重要环节,面试中经常考察评估指标和方法。

# 常见问题

1. 分类模型评估指标?
   - 准确率:正确预测的样本比例
   - 精确率:预测为正的样本中实际为正的比例
   - 召回率:实际为正的样本中预测为正的比例
   - F1分数:精确率和召回率的调和平均
   - ROC曲线:不同阈值下的TPR和FPR
   - AUC:ROC曲线下的面积

2. 回归模型评估指标?
   - MSE:均方误差
   - RMSE:均方根误差
   - MAE:平均绝对误差
   - R2:决定系数
   - 调整R2:考虑特征数量的R2

3. 交叉验证方法?
   - K折交叉验证:将数据分为K份
   - 留一法:每次留一个样本作为测试集
   - 分层交叉验证:保持类别比例
   - 时间序列交叉验证:考虑时间顺序

4. 过拟合和欠拟合?
   - 过拟合:模型在训练集表现好,测试集表现差
   - 欠拟合:模型在训练集和测试集表现都差
   - 解决方法:正则化、早停、数据增强

# 代码示例
import numpy as np
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score,
    f1_score, roc_auc_score, mean_squared_error,
    r2_score
)
from sklearn.model_selection import cross_val_score

# 1. 分类模型评估
def evaluate_classification(y_true, y_pred, y_pred_proba=None):
    metrics = {
        'accuracy': accuracy_score(y_true, y_pred),
        'precision': precision_score(y_true, y_pred),
        'recall': recall_score(y_true, y_pred),
        'f1': f1_score(y_true, y_pred)
    }
    
    if y_pred_proba is not None:
        metrics['auc'] = roc_auc_score(y_true, y_pred_proba)
    
    return metrics

# 2. 回归模型评估
def evaluate_regression(y_true, y_pred):
    metrics = {
        'mse': mean_squared_error(y_true, y_pred),
        'rmse': np.sqrt(mean_squared_error(y_true, y_pred)),
        'r2': r2_score(y_true, y_pred)
    }
    return metrics

# 3. 交叉验证
def cross_validate_model(model, X, y, cv=5):
    scores = cross_val_score(
        model, X, y,
        cv=cv,
        scoring='accuracy'
    )
    return scores.mean(), scores.std()

# 4. 学习曲线
def plot_learning_curve(model, X, y):
    from sklearn.model_selection import learning_curve
    import matplotlib.pyplot as plt
    
    train_sizes, train_scores, test_scores = learning_curve(
        model, X, y,
        cv=5,
        n_jobs=-1,
        train_sizes=np.linspace(0.1, 1.0, 10)
    )
    
    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)
    
    plt.figure(figsize=(10, 6))
    plt.plot(train_sizes, train_mean, label='训练集得分')
    plt.plot(train_sizes, test_mean, label='测试集得分')
    plt.fill_between(train_sizes,
                     train_mean - train_std,
                     train_mean + train_std,
                     alpha=0.1)
    plt.fill_between(train_sizes,
                     test_mean - test_std,
                     test_mean + test_std,
                     alpha=0.1)
    plt.xlabel('训练样本数')
    plt.ylabel('得分')
    plt.title('学习曲线')
    plt.legend()
    plt.show()