【机器学习之模型融合】Voting投票法简单实践

news2024/11/23 0:58:44

目录

前言💜

1、使用sklearn实现投票法💔

1.1、导入工具库,准备数据💕

1.2、定义交叉验证评估函数💖 

1.3、建立基于交叉验证的benchmark、做模型选择🌟

1.4、构建多组分类器、进行融合💥

1.5、构建多样性🎶

1.5.1、多种多样性混合👋

1.5.2、剔除表现不良的算法🐷

1.5.3、尝试精简多样性🐟

2、分类器加权🌷

3、总结💝


前言💜

Voting投票法基础知识参考:http://t.csdn.cn/1DVVl

1、使用sklearn实现投票法💔


1.1、导入工具库,准备数据💕

#常用工具库
import re
import numpy as np
import pandas as pd
import matplotlib as mlp
import matplotlib.pyplot as plt
import time

#算法辅助 & 数据
import sklearn
from sklearn.model_selection import KFold, cross_validate
from sklearn.datasets import load_digits #分类 - 手写数字数据集
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split

#算法(单一学习器)
from sklearn.neighbors import KNeighborsClassifier as KNNC
from sklearn.neighbors import KNeighborsRegressor as KNNR
from sklearn.tree import DecisionTreeRegressor as DTR
from sklearn.tree import DecisionTreeClassifier as DTC
from sklearn.linear_model import LinearRegression as LR
from sklearn.linear_model import LogisticRegression as LogiR
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.ensemble import GradientBoostingRegressor as GBR
from sklearn.ensemble import GradientBoostingClassifier as GBC
from sklearn.naive_bayes import GaussianNB
import xgboost as xgb

#融合模型
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import VotingRegressor

使用sklearn自带的手写数字数据集,是一个10分类数据集。

data = load_digits()
X = data.data
y = data.target
  • 我们将在Xtrain,Ytrain上进行交叉验证,并在Xtest,Ytest上进行最后的测试。
  • 我们的目标是:交叉验证的结果尽量好(理论泛化能力强),同时测试集上的结果也需要尽量好(理论泛化能力的验证,但不完全严谨)。当两者不可兼得时,我们优先考虑交叉验证的结果(理论泛化能力强)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.2,random_state=1412)

1.2、定义交叉验证评估函数💖 

def individual_estimators(estimators):
    """
    对模型融合中每个评估器做交叉验证,对单一评估器的表现进行评估
    """
    for estimator in estimators:
        cv = KFold(n_splits=5,shuffle=True,random_state=1412)
        results = cross_validate(estimator[1],Xtrain,Ytrain
                             ,cv = cv
                             ,scoring = "accuracy"
                             ,n_jobs = -1
                             ,return_train_score = True
                             ,verbose=False)
        test = estimator[1].fit(Xtrain,Ytrain).score(Xtest,Ytest)
        print(estimator[0]
          ,"\n train_score:{}".format(results["train_score"].mean())
          ,"\n cv_mean:{}".format(results["test_score"].mean())
          ,"\n test_score:{}".format(test)
          ,"\n")
  • train_score:模型在训练集上进行训练的得分表现的均值
  • cv_mean:模型通过交叉验证在验证集上的得分表现的均值
  • test_score:训练好的模型在测试集上的得分表现
def fusion_estimators(clf):
    """
    对融合模型做交叉验证,对融合模型的表现进行评估
    """
    cv = KFold(n_splits=5,shuffle=True,random_state=1412)
    results = cross_validate(clf,Xtrain,Ytrain
                             ,cv = cv
                             ,scoring = "accuracy"
                             ,n_jobs = -1
                             ,return_train_score = True
                             ,verbose=False)
    test = clf.fit(Xtrain,Ytrain).score(Xtest,Ytest)
    print("train_score:{}".format(results["train_score"].mean())
          ,"\n cv_mean:{}".format(results["test_score"].mean())
          ,"\n test_score:{}".format(test)
         )

1.3、建立基于交叉验证的benchmark、做模型选择🌟

一般在模型融合之前,我们需要将所有可能的算法都先简单运行一次,然后从中选出表现较好的算法作为融合的基础。同时,我们还可能在分数最高的单一算法上进行精确的调优,找到单一算法可以实现的最好分数来作为benchmark。毕竟,融合要求使用多个算法、自然也会在运算时间和算力上有所要求,如果单一算法的结果能够胜过融合,那我们优秀选择单一算法。我们使用备选分类器中的逻辑回归作为benchmark

logi = LogiR(max_iter=3000, n_jobs=8) #初始情况下给与一个较大的max_iter,方便迭代到收敛

fusion_estimators(logi) #正处于过拟合状态,需要调整


1.4、构建多组分类器、进行融合💥

  • 第一组分类器:放任自由,收敛为主,有较高过拟合风险
  • 逻辑回归+随机森林+梯度提升树
clf1 = LogiR(max_iter = 3000,random_state=1412,n_jobs=8)
clf2 = RFC(n_estimators= 100,random_state=1412,n_jobs=8)
clf3 = GBC(n_estimators= 100,random_state=1412)

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2), ("GBDT",clf3)]
clf = VotingClassifier(estimators,voting="soft")

  • 不难发现,每个模型在训练集上的分数都达到了1,但交叉验证分数大约在96%~97%之间,与逻辑回归的benchmark展现出来的结果相同。
  • 模型都存在一定的过拟合情况,其中GBDT在测试数据上表现出来的泛化能力有很大的问题,需要较为激进的调整。

很明显,通过集成模型的表现有了显著提升,交叉验证分数(97.77%)比任何单一学习器都高,且在测试集上的表现提升到了98.05%,可见当前数据下模型融合的效果十分显著。

并不是任意评估器、任意数据上都能够看到如此一目了然的结果。如果你进行投票或平均融合之后,融合的结果反而没有单个算法好,那你可能是落入了投票法与平均法会失效的几大陷阱

  1. 评估器之间的学习能力/模型表现差异太大。在融合中,一个表现很差的模型会拉低整个融合模型的上限,尤其是回归类算法,当一个模型的表现很差时,平均法得出的结果很难比最好的单一算法还好。因此我们必须要使用表现相似的模型进行融合。如果你的评估器中有拖后腿的模型,无论这个模型有多么先进,都应该立刻把它剔除融合模型。
     
  2. 评估器在类型上太相似,比如、全是树模型、都是Boosting算法,或都是线性评估器等。如果评估器类别太相似,模型融合会发挥不出作用,这在直觉上其实很好理解:如果平均/投票的评估器都一致,那融合模型最终得出的结果也会与单个评估器一致。
     
  3. 对评估器进行了过于精密的调优。一般来说,我们可能会认为,先对模型进行调优后再融合,能够进一步提升模型的表现。经过粗略调优的评估器融合确实能提升模型表现,但如果对评估器进行过于精密的调优,可能会让融合后的算法处于严重过拟合的状态。因此,一般我们不会在评估器上进行太精准的调优。

  • 第二组分类器:略微调参(非精细化调参),限制过拟合
  • 模型融合是一个可能加剧过拟合的手段,因此我们必须保证每一个学习器本身的过拟合不严重,为此我们需要对模型进行抗过拟合的处理。需要注意的是,对抗过拟合可能会削弱模型的预测效果,因此我们必须根据过拟合的情况、泛化能力的展现来进行选择。
  • 对于逻辑回归,我们需要缩小参数C,对随机森林我们选择max_depth,对GBDT我们则选择max_features
clf1 = LogiR(max_iter = 3000, C=0.1, random_state=1412,n_jobs=8) #这一组合可能说明我们的max_iter设置得太大了
clf2 = RFC(n_estimators= 100,max_depth=12,random_state=1412,n_jobs=8)
clf3 = GBC(n_estimators= 100,max_features="sqrt",random_state=1412)

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2), ("GBDT",clf3)]
clf = VotingClassifier(estimators,voting="soft")

  • 针对逻辑回归的调整效果不是非常明显,交叉验证的分数并未得到明显提升,但测试集上的结果上升,说明模型的泛化能力变得更加稳定了。但C参数是很少小于0.5的,我们现在得出的结果可能说明模型的权重是非常非常小的数,所以我们必须给与很小的C才能够加强过拟合的影响。
  • 随机森林的过拟合变得更加严重了,这说明我们限制过拟合对模型带来的伤害大于对模型的帮助,因此随机森林的过拟合是失败的,应该取消这种过拟合限制。
  • GBDT的过拟合调整是非常成功的,交叉验证分数上升的同时,测试集上的分数也得到了大幅提升。
  • 结论是,我们保留对逻辑回归和GBDT的调整,撤销对随机森林的调整
clf1 = LogiR(max_iter = 3000, C=0.1, random_state=1412,n_jobs=8) #这一组合可能说明我们的max_iter设置得太大了
clf2 = RFC(n_estimators= 100,random_state=1412,n_jobs=8)
clf3 = GBC(n_estimators= 100,max_features="sqrt",random_state=1412)

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2), ("GBDT",clf3)]
clf = VotingClassifier(estimators,voting="soft")


可以看到,经过过拟合调整后,模型的交叉验证分数与测试集上的分数都上升了,不过交叉验证分数是轻微上升(从0.9777392上升至0.9777463),这轻微的上升可以忽略不计。测试集上的分数则有了0.06%的提升,是一个显著的进步。

1.5、构建多样性🎶

无论是投票法还是平均法,都与Bagging算法有异曲同工之妙,因此我们相信“独立性”也有助于提升投票融合与平均融合的效果。在模型融合当中,独立性被称为“多样性”(diversity),评估器之间的差别越大、彼此之间就越独立,因此评估器越多样,独立性就越强。完全独立的评估器在现实中几乎不可能实现,因为不同的算法执行的是相同的预测任务,更何况大多数时候算法们都在相同的数据上训练,因此评估器不可能完全独立。但我们有以下关键的手段,用来让评估器变得更多样、让评估器之间相对独立:

  • 训练数据多样性:完成多组有效的特征工程,使用不同的特征矩阵训练不同的模型。该方法一般能够得到很好的效果,但如何找出多组有效的特征工程是难题。
     
  • 样本多样性:使用相同特征矩阵,但每次训练时抽样出不同的样本子集进行训练。当数据量较小时,抽样样本可能导致模型效果急剧下降。
     
  • 特征多样性:使用相同特征矩阵,但每次训练时抽样出不同的特征子集进行训练。当特征量较小时,抽样特征可能导致模型效果急剧下降。
     
  • 随机多样性/训练多样性:使用相同的算法,但使用不同的随机数种子(会导致使用不同的特征、样本、起点)、或使用不同的损失函数、使用不同的不纯度下降量等。这一方法相当于是在使用Bagging集成。
     
  • 算法多样性:增加类型不同的算法,如集成、树、概率、线性模型相混合。但需要注意的是,模型的效果不能太糟糕,无论是投票还是平均法,如果模型效果太差,可能大幅度降低融合的结果。

增加多样性的操作或多或少都阻止了模型学习完整的数据,因此会削弱模型对数据的学习,可能降低模型的效果。因此我们使用多样性时,需要时刻关注着模型的结果。


1.5.1、多种多样性混合👋

#逻辑回归没有增加多样性的选项
clf1 = LogiR(max_iter = 3000, C=0.1, random_state=1412,n_jobs=8)
#增加特征多样性与样本多样性
clf2 = RFC(n_estimators= 100,max_features="sqrt",max_samples=0.9, random_state=1412,n_jobs=8)
#特征多样性,稍微上调特征数量
clf3 = GBC(n_estimators= 100,max_features=16,random_state=1412) 

#增加算法多样性,新增决策树、KNN、贝叶斯
clf4 = DTC(max_depth=8,random_state=1412)
clf5 = KNNC(n_neighbors=10,n_jobs=8)
clf6 = GaussianNB()

#新增随机多样性,相同的算法更换随机数种子
clf7 = RFC(n_estimators= 100,max_features="sqrt",max_samples=0.9, random_state=4869,n_jobs=8)
clf8 = GBC(n_estimators= 100,max_features=16,random_state=4869)

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2)
              , ("GBDT",clf3), ("Decision Tree", clf4), ("KNN",clf5) 
              , ("Bayes",clf6), ("RandomForest2", clf7), ("GBDT2", clf8)
             ]
clf = VotingClassifier(estimators,voting="soft")


贝叶斯在训练集上的分数很低,这说明模型的学习能力不足

1.5.2、剔除表现不良的算法🐷

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2)
              , ("GBDT",clf3), ("Decision Tree", clf4), ("KNN",clf5) 
              #, ("Bayes",clf6) 贝叶斯在训练集上的分数很低,这说明模型的学习能力不足
              , ("RandomForest2", clf7), ("GBDT2", clf8)
             ]
clf = VotingClassifier(estimators,voting="soft")



1.5.3、尝试精简多样性🐟

estimators = [("Logistic Regression",clf1), ("RandomForest", clf2)
              , ("GBDT",clf3), ("Decision Tree", clf4), ("KNN",clf5) 
              #, ("Bayes",clf6), ("RandomForest2", clf7), ("GBDT2", clf8)
             ]
clf = VotingClassifier(estimators,voting="soft")



  • 在增加算法多样性的过程中,我们尝试了多种算法组合。我们发现朴素贝叶斯对算法的伤害大于贡献,只要将朴素贝叶斯包括在融合算法内,算法的表现就持续停留在97%左右,无法继续上升。因此我们删除了朴素贝叶斯算法。
  • 同时,包含随机多样性的算法组合在交叉验证与测试集结果上的表现高度一致,其中测试集结果略有降低、交叉验证结果提升了不少,这是一组可以使用的结果。但考虑到运算的效率,我们尽量不增加运算缓慢的集成算法,因此我们又将随机多样性删除,观察只包含5个算法的融合模型,最终交叉验证上的结果略有降低、测试集结果突破新高,这也是一组可以使用的结果。从模型的稳定性来考虑,还是包含随机多样性的组合更好,但为了更快的运算速率,我们可以使用精简多样性继续往下计算。

2、分类器加权🌷

  • 对分类器加权是一个常见的操作,但如何选择权重却是整个模型融合过程中最令人头疼的问题——头疼主要在于,没有可以完全依赖的理论基础或数学公式去进行权重推导(或者说推导出来的权重基于过多假设、无法使用),同时费了很大精力求解出的权重可能对模型的效果完全没有影响。因此,在融合中加权是一个不经济的选项。但一般来说,我们还是会尝试几组权重来探索一下,模型是否还有提升的空间。
  • 在机器学习算法中,只有一类算法对于评估器权重有自己的见解,那就是Boosting算法。在大部分Boosting集成过程中,我们会对每一个弱评估器求解其权重,并让权重作为迭代的一部分构建模型。那我们通常如何决定模型权重呢?在AdaBoost和XGBoost当中,我们都设立了用于衡量单个弱评估器置信度的某个指标,如果一个弱评估器的置信度越高,我们给与这个评估器的权重就越大。在Boosting算法中,置信度往往使用损失函数或损失函数的某种变体进行衡量,如果损失函数越大,则说明评估器的置信度越低,反之,则说明评估器的置信度越高。我们可以沿用这个思路,在模型融合中,我们会考虑的第一组权重,就是模型实际评估结果之间的比例。
  • 如果模型评估指标是准确率这样的正向指标,则直接使用准确率作为权重。如果模型评估指标是MSE这样的负向指标,则使用1-指标或负指标作为权重。这样做的风险在于,模型可能陷入严重过拟合,但值得一试。

  • 第一种选项:使用各个模型交叉验证结果本身作为权重,有过拟合风险
estimators = [("Logistic Regression",clf1), ("RandomForest", clf2)
              , ("GBDT",clf3), ("Decision Tree", clf4), ("KNN",clf5)]

clf_weighted = VotingClassifier(estimators,voting="soft",weights=[0.96660,0.97357,0.97774,0.85528,0.97634])

  • 可以看到,模型在交叉验证上的效果提升了!模型没有陷入过拟合,这是一个很好的消息。
  • 接下来,我们可以尝试使用更粗糙的权重来提升模型表现。一般来说,这个操作可以一定程度上缓解模型的过拟合。
  • 第二种选项:稍微降低权重精度,或许可以一定程度上抵消过拟合
clf_weighted = VotingClassifier(estimators,voting="soft",weights=[0.95,0.95,0.95,0.85,0.98])

  • 可以看到,模型的表现并无变化,这说明对当前数据来说,精确的权重与粗略的权重差异不大。
  • 接下来,我们可以尝试调整模型中效果最好、或效果最差的算法的权重。一般,可以尝试加大效果好的算法的权重,减小效果差的算法的权重。
  • 第三种选项加大效果好的算法的权重,减小效果差的算法的权重
clf_weighted = VotingClassifier(estimators,voting="soft",weights=[0.95,0.95,0.95,0.85,1.2]) #增大

不难发现,过拟合开始发生了,测试集上的结果开始降低。因此我们选择不加大效果好的算法的权重

clf_weighted = VotingClassifier(estimators,voting="soft",weights=[0.95,0.95,0.95,0.3,0.98]) #减小

模型达到了目前为止,在5折交叉验证及测试分数上的最高值。现在我们给与决策树的权重非常小,说明现在决策树只是在提供多样性,在实际预测方面做出的贡献较少。提供多样性可以让模型的泛化能力增强,让实际预测方面的贡献变小又可以降低决策树本身较低的预测分数带来的影响。至此,我们就得到了一个很好的融合结果。


3、总结💝

  1. 模型融合是一个不断探索、不断对抗过拟合的过程。
  2. 有的时候经过复杂的调参后,融合模型的效果可能还不如调整之前的表现。
  3. 构建多样性,放大模型之间的独立性,是提高融合模型效果的不错选择。
  4. Voting投票法原理不难,但是在实际应用中追求模型的最优表现,是要有经验的、是得花功夫的。
  5. 对于Averaging平均法而言,与Voting投票法原理和应用很相似,sklearn中的sklearn.ensemble.VotingRegressor就是对未拟合估计器的预测投票回归,所以不再赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单线程的Node.js能开发高并发服务器程序吗?

文章目录前言Nodejs的事件驱动机制EventLoop vs NSRunLoopNSRunLoopios next runloop异步/事件循坏机制的那些坑批量迁移数据原子性参考文献前言 这篇文章还是从一个在写Node.js程序中遇到的问题说起。本周在做数据库迁移的时候,写了下面一段代码,目的是…

代数与逻辑:作业四 神经网络

代数与逻辑:作业四 神经网络 文章目录代数与逻辑:作业四 神经网络一、作业要求二、简述神经网络模型三、编程实现感知机模型与二隐层神经网络1、感知机模型2、二隐层神经网络四、选择公开数据集,测试感知机模型与二隐层神经网络性能一、作业要…

如何高效学习?一年学完麻省理工4年计算机课程

斯科特.杨用用10天拿下线性代数,用1年时间学完麻省理工大学4年的计算机课程,他是如何做到的?他在这本书《如何高效学习》中做了具体阐述。 斯科特.杨很早就发现,在美国有一半的学生在死记硬背,这些学生并不知道使用整体…

动手学区块链学习笔记(二):区块链以及工作量证明算法

引言 紧接上文,在介绍完区块链中的加密解密以及公钥私钥等算法后,本篇开始正式进入区块链概念与一个简单区块链系统的实现过程介绍。 区块链技术介绍 什么是区块链? 区块链,就是一个又一个区块组成的链条。每一个区块中保存了一…

制造企业数据/经营分析框架

背景 随着大数据技术发展以及数字化转型概念的普及,传统企业特别是制造业,也开始投入人力、资金,建立自己的数据分析团队,期望通过数据分析赋能企业的发展/转型。尽管,国内华为、美的、海尔、三一、徐工等制造业龙头企…

挡不住,逃不过,还是阳了

自从放开后,身边的🐏陆陆续续多了起来。现在都不敢在食堂吃饭了,每次都是打包到工位吃,上班时也是都戴着口罩。每天回家后都是一顿扫射,用医用酒精做全身消毒。但是,还是没挡住,该来的还是来了。…

Leetcode:450. 删除二叉搜索树中的节点(C++)

目录 问题描述: 实现代码与解析: 递归: 原理思路: 含有内存释放版: 问题描述: 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜…

Day860.高性能数据库连接池HiKariCP -Java 并发编程实战

高性能数据库连接池HiKariCP Hi,我是阿昌,今天学习记录的是关于高性能数据库连接池HiKariCP的内容。 实际工作中,总会难免和数据库打交道; 只要和数据库打交道,就免不了使用数据库连接池。 业界知名的数据库连接池…

2023/1/15 JS-作用域与作用域链

1 作用域 理解 - 就是一块"地盘", 一个代码段所在的区域,它是静态的(相对于上下文对象), 在编写代码时就确定了 分类: 全局作用域函数作用域 没有块作用域(ES6有了) -->(java语言也有) if (true) {var a 3}console.log(a); // 3作用&am…

用互联网思维做产品,做超出用户预期的产品

做出超出用户预期的产品,做出让用户惊喜和兴奋的产品。超越用户期望极致体验极致服务极致产品(极致产品功能情感温度)关心、关注、尊重用户理解用户理解人性用户参与。只有深刻了解,深刻理解用户,深刻理解人性,才能做出好的产品。…

Maven安装教程讲解

目录一、下载安装JDK二、下载 Maven三、配置 Maven 环境变量四、配置 Maven 仓库地址五、配置 Maven 镜像六、配置 Maven JDK七、IDE配置 Maven八、IDE新建 Maven 项目九、IDE执行 Maven 命令一、下载安装JDK 教程:https://blog.csdn.net/weixin_43888891/article/…

【阶段四】Python深度学习09篇:深度学习项目实战:循环神经网络处理时序数据项目实战:CNN和RNN组合模型

本篇的思维导图: 项目背景 时间序列数据集中的所有数据都伴随着一个时戳,比如股票、天气数据。这个数据集,是科学家们多年间用开普勒天文望远镜观察并记录下来的银河系中的一些恒星的亮度。广袤的宇宙,浩瀚的星空在过去很长一段时间里,人类是没有办法证明系外行星…

关于一次python服务性能的问题分析定位

今天项目遇到一个比较棘手的问题,我们做的接口平台,提供了一个给用户自己编辑关键字的逻辑,发现对应服务的cpu基本都满了,并且通过扩容的方式也没有好转,也同样被打满。 找了测试的同学了解了下,发现他们使…

Enterprise JavaBean 简介

Enterprise JavaBean 简介 在顶层我们使用的框架是面向服务的,而在其之下的开发方法面向组件,最基层的便是面向对象面向过程的JAVA编程。 面向过程和面向对象是两种具体程序设计时的编程范式,他们没有本质区别,只是使用不同的方…

【Linux】Linux命令行git和Linux调试器-gdb的使用

文章目录一、Linux命令行git1. git是什么2. Gitee上创建仓库,克隆仓库到本地3. git三板斧二、Linux调试器-gdb的使用1. debug和release的区别2. 常用命令一、Linux命令行git 1. git是什么 git是一个开源的分布式版本控制系统,可以有效、高速地处理从很…

分享52个Java源码,总有一款适合您

Java源码 分享52个Java源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下...,大家下载后可以看到。 源码下载链接:https://pan.baidu.com/s/1YpNL5QWwQ18Y-KRmFHFs5g?pwdqc8w …

吴恩达机器学习课程笔记:监督学习、无监督学习

1.吴恩达机器学习课程笔记:监督学习、无监督学习 吴恩达机器学习系列课程:监督学习 吴恩达机器学习系列课程:无监督学习 仅作为个人学习笔记,若各位大佬发现错误请指正 机器学习的学习算法:监督学习、无监督学习、半…

1591_AURIX_TC275_PMU_Flash的保护

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 可以支持保护功能的Flash是前面文档中呼出来的几块,其中DFlash由于多模块公用,还有具体的拆分。PFlash可以进行两方面的保护,一个是错误的读取方式保护&…

python列表(list)底层实现

list Python内存管理中的基石 Python中所有类型创建对象时,底层都是与PyObject和PyVarObject结构体实现,一般情况下由单个元素组成对象内部会使用PyObject结构体(float)、由多个元素组成的对象内部会使用PyVarObject结构体 2个…

应用层——电子邮件(SMTP、POP3、IMAP)

目录 1. 电子邮件系统及组成结构 1.1 电子邮件 1.2 电子邮件系统的组件 2. SMTP(邮件发送协议) 2.1 SMTP的特征 2.2 SMTP的基本操作 2.3 SMTP协议的基本流程 2.4 SMTP交互与应答 2.5 SMTP与HTTP的对比 3. 邮件报文格式与MIME 3.1 电子邮件格式 3.2 多用途网际…