datawhale-动手学数据分析task5笔记

LPF05 / 2024-03-22 / 原文

datawhale-动手学数据分析task5笔记

模型搭建和评估--建模

模型搭建前的准备

  1. 引入所需的库与数据。

  2. 对数据进行特征工程:从原始数据中提取有用的特征,以便机器学习算法能够更有效地进行学习和预测。

  3. 数据集导致模型在拟合数据时发生变化的常见差异:

    • 特征差异

    • 样本数量与分布差异

    • 噪声与异常值

    • 目标变量差异

    • 数据划分差异

    • 时间序列数据的时序差异

    • 数据预处理与清洗

模型搭建

sklearn的算法选择路径图:
sklearn

切割训练集和测试集

  1. 划分数据集的方法:

    • 简单随机抽样(Simple Random Sampling):

      从总体中随机选择样本,每个样本被选中的概率是相等的。
      适用于没有先验知识或特定结构的数据集。

    • 分层抽样(Stratified Sampling):

      根据某个或多个特征将数据分成不同的层或子集,然后从每层中随机抽取样本。
      常用于确保每个类别的样本在训练集、验证集和测试集中都有合适的比例。

    • 时间序列划分:

      对于时间序列数据,通常按照时间顺序划分数据集,如使用前80%的数据作为训练集,接下来的10%作为验证集,最后的10%作为测试集。
      这种划分方式有助于保持数据的时间依赖性,并防止未来数据泄露到训练集中。

    • K折交叉验证(K-fold Cross-validation):

      将数据集分成K个不相交的子集,每次使用K-1个子集作为训练集,剩下的一个子集作为验证集。
      这个过程重复K次,每次使用不同的子集作为验证集。
      最后,对K次验证的结果取平均值,得到模型的性能估计。

    • 留出法(Hold-out):

      将数据集随机划分为两个互斥的子集,一个作为训练集,另一个作为测试集。
      训练集用于训练模型,测试集用于评估模型的性能。
      这种方法简单且易于实现,但可能由于随机性导致性能评估的不稳定。

    • 自助法(Bootstrapping):

      采用有放回的随机抽样方式从原始数据集中抽取样本形成训练集,剩余的样本作为测试集。
      由于是有放回的抽样,自助法允许同一个样本在训练集中出现多次,或在训练集和测试集中同时出现。
      自助法产生的数据集改变了原始数据集的分布,因此在估计模型误差时可能引入偏差。

  2. 分层抽样法的优点:

    • 可以保持比例的代表性。

    • 使得样本分布更加均匀,提高估计的精度。

    • 确保每个类别在样本中都有足够的代表,可以减少抽样的误差。

  3. 随机抽样或分层抽样切割数据集的方法:train_test_split()

    '''
    参数说明:
    - train_data是所要划分的样本特征集
    - train_target是所要划分的样本结果
    - test_size=[0,1]/int,样本占比,如果是整数的话就是样本的数量,None时默认0.25
    - train_size,同上,test_size可替代,None时默认0.75
    - random_state=int/None,随机数种子,不同随机数种子划分的结果不同,None时每次种子随机
    - shuffle=Bool,如果True则会先将数据打乱顺序然后再进行划分
    - stratify=list/None,保持split前类的分布,也就是分层抽样的分层依据,如果想要依据train_target分类,可直接使stratify=train_target,None时随机抽样
    '''
    
    # 以下有具体值的为默认值
    from sklearn.model_selection import train_test_split
    x_train,x_test, y_train,y_test = train_test_split(train_data, train_target, test_size=None, train_size=None, random_state=None, shuffle=True, stratify=None)
    
  4. 不用进行随机选取情况:

    • 时间序列数据:随机打乱数据会破坏数据的时间依赖性和顺序性。

    • 特定顺序的数据:有些数据项之间可能存在特定的逻辑或物理顺序,例如图像中的连续帧。

    • 类别分布不平衡的数据:不同类别的样本数量差距可能很大,直接随机选取会导致某些类别样本在数据集中过少或过多。

    • 有特定结构的数据:数据可能具有特定的结构或模型,例如社交网络中的图或网络。

模型创建

Logistic Regression
  1. 逻辑回归(Logistic Regression)模型是线性模型的分类模型,不是回归模型,与LinearRegression混淆。

  2. Logistic Regression通过建立概率模型,将线性回归的输出结果通过逻辑函数(通常是sigmoid函数)转换为概率形式,从而进行分类预测(解决二分类问题)。

  3. 创建基于线性模型的分类模型(逻辑回归)的流程:

    # 引入LogisticRegression类
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import accuracy_score  
    
    # 划分数据集
    x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y)
    
    # 创建LogisticRegression类的示例(以下为默认参数)
    logreg = LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                                intercept_scaling=1, l1_ratio=None, max_iter=100,
                                multi_class='auto', n_jobs=None, penalty='l2',
                                random_state=None, solver='lbfgs', tol=0.0001, verbose=0,
                                warm_start=False)
    
    # 拟合模型
    logreg.fit(x_train, y_train)
    
    # 预测与评估准确度
    y_pred = logreg.predict(y_test)
    accuracy = accuracy_score(y_test, y_pred)
    
    logreg.score(x_test, y_test) # 评测数据与标签,y是y_test的教师标签
    
  4. LogisticRegression类的参数说明:

    h13

    h14

Decision Tree Classifier
  1. 分类决策树(DecisionTreeClassifier)是一种预测模型,主要用于解决分类问题,是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一个类别,基于这样的结构,根据样本的属性值进行逐步测试,最终将样本划分到某个叶节点,即某个类别中。

  2. 创建分类决策树的流程:

    # 引入DecisionTreeClassifier类
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.metrics import accuracy_score  
    
    # 划分数据集
    x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y)
    
    # 创建DecisionTreeClassifier类的示例(以下为默认参数)
    clf = DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None,
                                min_samples_split=2, min_samples_leaf=1, 
                                min_weight_fraction_leaf=0.0, max_features=None, random_state=None,     
                                max_leaf_nodes=None, min_impurity_decrease=0.0, class_weight=None, 
                                ccp_alpha=0.0, monotonic_cst=None)
    
    # 拟合模型
    clf.fit(x_train, y_train)
    
    # 预测与评估准确度
    y_pred = clf.predict(y_test)
    accuracy = accuracy_score(y_test, y_pred)
    
    clf.score(x_test, y_test) # 评测数据与标签,y是y_test的教师标签
    
  3. DecisionTreeClassifier类的参数说明:

    参数 类型 描述
    criterion 可选值为'gini'或'entropy', default='gini' 特征选择标准,默认'gini'即CART算法。
    splitter 可选值为'best'或'random', default='best' 用于在每个节点选择划分特征的算法。'best'表示在全局选择最优划分,'random'表示随机局部选择最优划分。
    max_depth int, default=None 树的最大深度。如果为None,则树会生长到所有叶子都是纯的,或者直到所有叶子包含少于min_samples_split的样本。
    min_samples_split int or float, default=2 拆分内部节点所需的最小样本数。如果是float,则表示的是占训练集样本总数的比例。
    min_samples_leaf int or float, default=1 一个叶子节点必须具有的最小样本数。如果是float,则它表示的是占训练集样本总数的比例。
    min_weight_fraction_leaf float, default=0.0 最小样本权重和,如果小于则会和兄弟节点一起被剪枝,这个参数用于处理带权重的样本。
    max_features int, float, string or None, default=None 考虑用于查找最佳划分的特征数量。如果是int,则随机考虑max_features个特征;如果是float,则max_features是特征总数的比例;如果是'sqrt',则max_features=sqrt(n_features);如果是'log2',则max_features=log2(n_features);如果是None,则max_features=n_features
    random_state int, RandomState instance or None, default=None 控制随机性的参数。对于splitter='random'时尤为重要。
    max_leaf_nodes int or None, default=None 最大叶子节点数。如果为None,则不限制叶子节点的数量。
    min_impurity_decrease float, default=0.0 如果一个分割点导致的不纯度减少小于这个值,则该分割点不会被考虑。
    class_weight dict, list of dict or "balanced", default=None 类别权重。如果为None,则所有类别的权重相等。如果为'balanced',则类别权重与类频率成反比。也可以提供一个字典,指定每个类别的权重。
    ccp_alpha float, default=0.0 复杂度参数用于最小成本-复杂度剪枝。增加此参数的值会导致树更早停止生长。
    monotonic_cst list of bools or None, default=None 如果给出,布尔值的列表,其长度等于类的数量,表示是否应该强制决策树为单调的。请注意,单调性仅适用于单变量分割的决策树。
Random Forest Classifier
  1. 分类随机森林(RandomForestClassifier)是一种集成学习方法,基于构建并结合多个决策树来提高模型的预测性能。随机森林通过随机有放回地抽取数据样本集来训练多个决策树,并且每个决策树在构建过程中也随机抽取特征进行划分。

  2. 创建分类随机森林的流程:

    # 引入RandomForestClassifier类
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import accuracy_score  
    
    # 划分数据集
    x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y)
    
    # 创建RandomForestClassifier类的示例(以下为默认参数)
    clf = RandomForestClassifier(n_estimators=100, criterion='gini', max_depth=None,
                                min_samples_split=2, min_samples_leaf=1,min_weight_fraction_leaf=0.0, 
                                max_features='sqrt', max_leaf_nodes=None, min_impurity_decrease=0.0,
                                bootstrap=True, oob_score=False, n_jobs=None, random_state=None, 
                                verbose=0, warm_start=False, class_weight=None, ccp_alpha=0.0, 
                                max_samples=None, monotonic_cst=None)
    
    # 拟合模型
    clf.fit(x_train, y_train)
    
    # 预测与评估准确度
    y_pred = clf.predict(y_test)
    accuracy = accuracy_score(y_test, y_pred)
    
    clf.score(x_test, y_test) # 评测数据与标签,y是y_test的教师标签
    
  3. RandomForestClassifier类的参数说明:

    参数名称 参数类型 描述
    n_estimators int, optional default=100 随机森林里的树木数量。
    criterion 可选值为"gini" 或 "entropy", str, optional default='gini' 用于测量分裂质量的函数。
    max_depth int or None, optional default=None 树的最大深度。如果为 None,则节点将展开直到所有叶子都是纯净的或者直到所有叶子包含少于 min_samples_split 的样本。
    min_samples_split int or float, optional default=2 分裂内部节点所需的最小样本数。
    min_samples_leaf int or float, optional default=1 一个叶节点应该具有的最小样本数。
    min_weight_fraction_leaf float, optional default=0.0 在叶子节点所有输入样本权重总和中的最小权重分数。
    max_features str, int or None, optional default='sqrt' 寻找最佳分裂时要考虑的特征数量。
    max_leaf_nodes int or None, optional default=None 最大叶节点数量。
    min_impurity_decrease float, optional default=0.0 如果这种分裂导致不纯度的减少大于或等于此值,则节点将被分裂。
    bootstrap bool, optional default=True 是否在构建树时使用自助法样本。
    oob_score bool, optional default=False 是否使用袋外样本来估计泛化误差。
    n_jobs int or None, optional default=None 用于运行的并行运行的线程数。如果为 -1,则使用所有可用的处理器。
    random_state int, RandomState instance or None, optional default=None 控制随机性的参数。
    verbose int, optional default=0 控制建树过程的日志输出的详细程度。
    warm_start bool, optional default=False 当设置为 True 时,重用解决方案的上一次调用的解作为初始化,否则,只需擦除之前的解决方案。
    class_weight dict, list of dict or "balanced", optional default=None 指定类别的权重。
    ccp_alpha non-negative float, optional default=0.0 复杂度参数用来最小化损失函数的正则化项。
    max_samples int or float, optional default=None 如果 bootstrap 为 True,则这是从 X 中抽取样本以构建每个基础学习器的样本数。
    monotonic_cst list of lists or array-like or None, optional default=None 约束树中的每个特征的单调性。

输出模型预测结果

  1. .predict()方法可以输出预测标签。

  2. .predict_proba()可以输出标签概率。
    predict_proba(X) 方法会返回一个数组,其形状为 (n_samples, n_classes),其中 n_samples 是输入样本的数量,n_classes 是目标变量的类别数。数组的每一个元素 [i, j] 表示第 i 个样本属于第 j 个类别的概率。

  3. 预测标签的概率可以用来调整阈值、估计不确定性、校准概率、指定调整决策等。

模型评估

模型评估的三种方法

  1. 模型评估是为了知道模型的泛化能力。

  2. 机器学习和数据科学中用于评估分类模型性能的三种工具方法:交叉验证、混淆矩阵和ROC曲线。

  3. 准确率(Precision)、召回率(Recall)和F-分数(F-score)是分类任务中常用的评估指标,它们可以帮助我们全面评估分类模型的性能。

    • 准确率:
      准确率表示模型预测为正样本的实例中,真正为正样本的比例。
      \(Precision = \dfrac{TP}{TP + FP}\)
      \(TP\)是真正例
      \(FP\)是假正例
      准确率越高,说明模型预测为正样本的实例中,错误预测的比例越低。

    • 召回率
      召回率表示实际为正样本的实例中,被模型预测为正样本的比例。
      \(Recall = \dfrac{TP}{TP + FN}\)
      \(FN\)是假负例
      召回率越高,说明模型能够找到更多的正样本,减少漏报的情况。

    • f-分数
      F-分数是准确率和召回率的调和平均值,用于综合评估模型的性能。
      $F-score = \dfrac{2 * precision * recall}{precision + recall} $
      F-分数越高,说明模型在准确率和召回率之间达到了较好的平衡。

交叉验证
  1. 交叉验证(cross-validation)是一种评估泛化性能的统计学方法,它比单次划分训练集和测试集的方法更加稳定、全面,主要用于防止模型过拟合。

  2. 交叉验证法的常见形式:

    • 简单交叉验证(Hold-out Cross-validation):
      将数据集分为训练集和测试集两部分。
      使用训练集训练模型,并在测试集上评估其性能。
      这种方法的优点是简单,但缺点是可能由于数据划分的随机性导致评估结果的不稳定。

    • K折交叉验证(K-fold Cross-validation):
      将数据集分成K个大小相等的子集(或尽可能相等)。
      每次选择K-1个子集作为训练集,剩下的一个子集作为验证集。
      进行K次迭代,每次使用不同的子集作为验证集。
      计算K次迭代的平均性能作为模型的最终评估结果。
      这种方法的优点是评估结果较为稳定,能够充分利用数据集进行训练和验证。

      h15

    • 留一交叉验证(Leave-one-out Cross-validation):
      当数据集非常小时,可以使用留一交叉验证。
      每次选择一个样本作为验证集,其余样本作为训练集。
      对于数据集中的每个样本都进行这样的操作,最终计算所有迭代的平均性能。
      这种方法的优点是评估结果非常稳定,但由于每次迭代只使用一个样本作为验证集,所以计算成本较高。

    • 分层交叉验证(Stratified Cross-validation):
      当数据集中各类别的样本数量不平衡时,可以使用分层交叉验证。
      在划分数据集时,确保每个子集中各类别的样本比例与原始数据集中的比例相同。
      这有助于避免由于类别不平衡导致的评估偏差。

    • 时间序列交叉验证(Time-series Cross-validation):
      适用于时间序列数据,其中数据的顺序非常重要。
      将数据按照时间顺序划分成多个子集,并确保训练集总是在验证集之前。
      这种方法有助于评估模型在时间序列预测任务中的性能。

  3. k-交叉验证的示例:

    # 引入cross_val_score函数
    from sklearn.model_seleciton import cross_val_score
    
    from sklearn.linear_model import LogisticRegression
    
    # 划分数据集并处理模型
    x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y)
    
    logreg = LogisticRegression()
    
    score = cross_val_score(logreg, x_train, y_train, cv=10)
    
    # k折交叉验证分数
    print(f"score:{score}")
    
    # 平均交叉验证分数
    print("Average cross-validation score: {:.2f}".format(scores.mean()))
    
  4. 不需要显示拟合模型.fit(),因为在交叉验证中会自动拟合模型。

  5. K值越多,意味着每次用于训练和验证的数据子集越小,同时验证的次数也越多,当k折越多时的影响:

    • 模型评估的稳定性增加

    • 计算量增加

    • 过拟合风险减小

    • 超参数选择更精确