机器学习本科课程 实验3 决策树处理分类任务

实验3.1 决策树处理分类任务

  1. 使用sklearn.tree.DecisionTreeClassifier完成肿瘤分类(breast-cancer)
  2. 计算最大深度为10时,十折交叉验证的精度(accuracy),查准率(precision),查全率(recall),F1值
  3. 绘制最大深度从1到10的决策树十折交叉验证精度的变化图

1. 读取数据

import numpy as np
import pandas as pd
data = pd.read_csv('breast-cancer.csv')
print(data.shape)
data.head()
data = data.values 
data_x = data[:,2:-1]
data_y = data[:,1:2]
data_y = np.reshape(data_y,(-1))


print(data_x.shape)
print(data_y.shape)

2. 导入模型

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.tree import DecisionTreeClassifier

3. 训练与预测

计算最大深度为10的决策树,在使用数据data_x,标记data_y下,十折交叉验证的精度,查准率,查全率和F1值

model = DecisionTreeClassifier(max_depth = 10) # 参数max_depth决定了决策树的最大深度


prediction = cross_val_predict(model,data_x,data_y,cv = 10)
 
acc1 = accuracy_score(data_y,prediction)
precision1 = precision_score(data_y,prediction,average="macro")
recall1 = recall_score(data_y,prediction,average="macro")
f1 = f1_score(data_y,prediction,average="macro")

print("决策树在data_测试集上的四项指标")
print("精度:",acc1)
print("查准率:",precision1)
print("查全率:",recall1)
print("f1值:",f1)

4. 改变最大深度,绘制决策树的精度变换图

绘制最大深度从1到10,决策树十折交叉验证精度的变化图

import matplotlib.pyplot as plt
%matplotlib inline

y = []

for i in range(10):
    model = DecisionTreeClassifier(max_depth = i + 1)
    prediction = cross_val_predict(model,data_x,data_y,cv=10)
    y.append(prediction)
    
x = np.linspace(1,10,10)
test = [accuracy_score(data_y, val) for val in y]

plt.figure()
plt.plot(x,test,'-')
plt.title("DecisionTree's accuracy_score changes with the max_depth")
plt.xlabel("max_depth")    
plt.ylabel("accuracy_score")

5. 通过调整参数,得到一个泛化能力最好的模型

查看决策树文档,通过调整决策树的参数,得到一个最好的模型
http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier
并在下方给出参数的设定与其泛化性能指标
请添加图片描述

criterion:用于衡量特征选择质量的准则。可以是"gini"(基尼系数)或"entropy"(信息增益)。
max_depth:决策树的最大深度。控制树的复杂度和过拟合的风险。
min_samples_split:拆分内部节点所需的最小样本数。
min_samples_leaf:叶子节点所需的最小样本数。
max_features:寻找最佳分割时要考虑的特征数量。
random_state:控制随机性的种子值。

使用的GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化的结果和参数。
但是这个方法适合于小数据集,一旦数据的量级上去了,很难得出结果。

from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import StratifiedKFold
modelfit = DecisionTreeClassifier(max_depth = 10)
param_grid = {'criterion':['gini','entropy'],'max_depth':[10,11,12],
                  'min_samples_leaf':[1,2,3,4,5],'max_features':[1,2,3,4,5],'min_samples_split':[2,3,4,5]}

grid = GridSearchCV(modelfit,param_grid,cv = 10)

grid.fit(data_x,data_y)

best = grid.best_params_  #最优分类器
print(best)
best_decision_tree_classifier = DecisionTreeClassifier(max_depth = best['max_depth'],max_features=best['max_features'],
                                                       min_samples_leaf = best['min_samples_leaf'],min_samples_split = best['min_samples_split'])
# your code
prediction11 = cross_val_predict(model, data_x, data_y, cv=10)
acc11 = accuracy_score(data_y, prediction)
precision11 = precision_score(data_y, prediction, average="macro")
recall11 = recall_score(data_y, prediction, average="macro")
f1_11 = f1_score(data_y, prediction, average="macro")
print("-------------------")
print("精度:", acc11)
print("查准率:", precision11)
print("查全率:", recall11)
print("f1值:", f1_11)
双击此处填写优化后的决策树参数设置与性能指标的结果

参数设置:

划分标准-基尼系数; 最大深度-10; 最大特征数-5; 叶子节点最少样本数-5; 内部节点再划分所需最小样本数-3;

性能指标得分:

  • 精度: 0.9104

  • 查准率: 0.9033

  • 查全率: 0.9056

  • f1值: 0.9044

实验3.2决策树处理回归任务

  1. 使用sklearn.tree.DecisionTreeRegressor完成kaggle房价预测问题
  2. 计算最大深度为10的决策树,训练集上十折交叉验证的MAE和RMSE
  3. 绘制最大深度从1到30,决策树在训练集和测试集上MAE的变化曲线
  4. 选择一个合理的树的最大深度,并给出理由

1. 读取数据

import pandas as pd
data = pd.read_csv('train.csv')
# 丢弃有缺失值的特征(列)
data.dropna(axis = 1, inplace = True)

# 只保留整数的特征
data = data[[col for col in data.dtypes.index if data.dtypes[col] == 'int64']]

2. 数据集划分

70%做训练集,30%做测试集

from sklearn.utils import shuffle
data_shuffled = shuffle(data, random_state = 32)
split_line = int(len(data_shuffled) * 0.7)
training_data = data_shuffled[:split_line]
testing_data = data_shuffled[split_line:]

3. 导入模型

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
from sklearn.tree import DecisionTreeRegressor
import numpy as np

4. 选取特征和标记

features = data.columns.tolist()
target = 'SalePrice'
features.remove(target)

5. 训练与预测

请你在下面计算树的最大深度为10时,使用训练集全量特征训练的决策树的十折交叉验证的MAE和RMSE

# YOUR CODE HERE
# training_data[features]
# training_data[target]
model12 = DecisionTreeRegressor(max_depth = 10)
model12.fit(training_data[features], training_data[target])
predictions12 = model12.predict(testing_data[features])

mae12 = mean_absolute_error(testing_data[target], predictions12)
mse12 = mean_squared_error(testing_data[target], predictions12)
rmse12 = np.sqrt(mse12)

print("Mean Absolute Error:", mae12)
print("Mean Squared Error:", mse12)
print("Root Mean Squared Error:", rmse12)

6. 改变最大深度,绘制决策树的精度变换图

绘制最大深度从1到30,决策树训练集和测试集MAE的变化图

import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use("fivethirtyeight")
# YOUR CODE HERE
y12 = []

for i in range(30):
    model12 =  DecisionTreeRegressor(max_depth = i+1)
    model12.fit(training_data[features], training_data[target])
    predictions12 = model12.predict(testing_data[features])
    
    mae12 = mean_absolute_error(testing_data[target], predictions12)
    mse12 = mean_squared_error(testing_data[target], predictions12)
    rmse12 = np.sqrt(mse12)
    y12.append(mae12)

    print('----------------------')
    print("max_depth: ", i+1)
    print("Mean Absolute Error:", mae12)
    print("Mean Squared Error:", mse12)
    print("Root Mean Squared Error:", rmse12)

x12 = np.linspace(1, 30, 30)

plt.figure()
plt.plot(x12, y12, '-')
plt.title("DecisionTree's MAE changes with the max_depth")
plt.xlabel("max_depth")
plt.ylabel("MAE")

7. 请你选择一个合理的树的最大深度,并给出理由

请你选择一个合理的树的最大深度,并给出理由

根据走势图, 我认为选择最大深度为6比较合适, 当最大深度到达6附近, MAE接近全局最小值, 而当最大深度增大时, 对模型的性能没有明显的增益, 甚至增大一定程度后会造成MAE值的波动, 因此在效率和精度的双重考虑下选择最大深度为6

实验3.3实现决策树

使用LendingClub Safe Loans数据集:

  1. 实现信息增益、信息增益率、基尼指数三种划分标准
  2. 使用给定的训练集完成三种决策树的训练过程
  3. 计算三种决策树在最大深度为10时在训练集和测试集上的精度,查准率,查全率,F1值
  4. 画出决策树(选作)

在这部分,我们会实现一个很简单的二叉决策树

1. 读取数据

# 导入类库
import pandas as pd
import numpy as np
import json
# 导入数据
loans = pd.read_csv('lending-club-data.csv', low_memory=False)

数据中有两列是我们想预测的指标,一项是safe_loans,一项是bad_loans,分别表示正例和负例,我们对其进行处理,将正例的safe_loans设为1,负例设为-1,删除bad_loans这列

# 对数据进行预处理,将safe_loans作为标记
loans['safe_loans'] = loans['bad_loans'].apply(lambda x : +1 if x==0 else -1)
del loans['bad_loans']

我们只使用grade, term, home_ownership, emp_length这四列作为特征,safe_loans作为标记,只保留loans中的这五列

features = ['grade',              # grade of the loan
            'term',               # the term of the loan
            'home_ownership',     # home_ownership status: own, mortgage or rent
            'emp_length',         # number of years of employment
           ]
target = 'safe_loans'
loans = loans[features + [target]]

2. 划分训练集和测试集

from sklearn.utils import shuffle
loans = shuffle(loans, random_state = 34)

split_line = int(len(loans) * 0.6)
train_data = loans.iloc[: split_line]
test_data = loans.iloc[split_line:]

3. 特征预处理

可以看到所有的特征都是离散类型的特征,需要对数据进行预处理,使用one-hot编码对其进行处理。
one-hot编码的思想就是将离散特征变成向量,假设特征 A A A有三种取值 { a , b , c } \{a, b, c\} {a,b,c},这三种取值等价,如果我们使用1,2,3三个数字表示这三种取值,那么在计算时就会产生偏差,有一些涉及距离度量的算法会认为,2和1离得近,3和1离得远,但这三个值应该是等价的,这种表示方法会造成模型在判断上出现偏差。解决方案就是使用一个三维向量表示他们,用 [ 1 , 0 , 0 ] [1, 0, 0] [1,0,0]表示a, [ 0 , 1 , 0 ] [0, 1, 0] [0,1,0]表示b, [ 0 , 0 , 1 ] [0, 0, 1] [0,0,1]表示c,这样三个向量之间的距离就都是相等的了,任意两个向量在欧式空间的距离都是 2 \sqrt{2} 2 。这就是one-hot编码是思想。
pandas中使用get_dummies生成one-hot向量

def one_hot_encoding(data, features_categorical):
    '''
    Parameter
    ----------
    data: pd.DataFrame
    
    features_categorical: list(str)
    '''
    
    # 对所有的离散特征遍历
    for cat in features_categorical:
        
        # 对这列进行one-hot编码,前缀为这个变量名
        one_encoding = pd.get_dummies(data[cat], prefix = cat)
        
        # 将生成的one-hot编码与之前的dataframe拼接起来
        data = pd.concat([data, one_encoding],axis=1)
        
        # 删除掉原始的这列离散特征
        del data[cat]
    
    return data

首先对训练集生成one-hot向量,然后对测试集生成one-hot向量,这里需要注意的是,如果训练集中,特征 A A A的取值为 { a , b , c } \{a, b, c\} {a,b,c},这样我们生成的特征就有三列,分别为 A _ a A\_a A_a, A _ b A\_b A_b, A _ c A\_c A_c,然后我们使用这个训练集训练模型,模型就就会考虑这三个特征,在测试集中如果有一个样本的特征 A A A的值为 d d d,那它的 A _ a A\_a A_a A _ b A\_b A_b A _ c A\_c A_c就都为0,我们不去考虑 A _ d A\_d A_d,因为这个特征在训练模型的时候是不存在的。

train_data = one_hot_encoding(train_data, features)
train_data.head()
one_hot_features = train_data.columns.tolist()
one_hot_features.remove(target)
one_hot_features

接下来是对测试集进行one_hot编码,但只要保留出现在one_hot_features中的特征即可

test_data_tmp = one_hot_encoding(test_data, features)
# 创建一个空的DataFrame
test_data = pd.DataFrame(columns = train_data.columns)
for feature in train_data.columns:
    # 如果训练集中当前特征在test_data_tmp中出现了,将其复制到test_data中
    if feature in test_data_tmp.columns:
        test_data[feature] = test_data_tmp[feature].copy()
    else:
        # 否则就用全为0的列去替代
        test_data[feature] = np.zeros(test_data_tmp.shape[0], dtype = 'uint8')
        
test_data.head()

处理完后,所有的特征都是0和1,标记是1和-1,以上就是数据预处理流程

4. 实现3种特征划分准则

决策树中有很多常用的特征划分方法,比如信息增益、信息增益率、基尼指数

我们需要实现一个函数,它的作用是,给定决策树的某个结点内的所有样本的标记,让它计算出对应划分指标的值是多少

接下来我们会实现上述三种划分指标

这里我们约定,将所有特征取值为0的样本,划分到左子树,特征取值为1的样本,划分到右子树

4.1 信息增益

信息熵:
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ p k l o g 2 p k \mathrm{Ent}(D) = - \sum^{\vert \mathcal{Y} \vert}_{k = 1} p_k \mathrm{log}_2 p_k Ent(D)=k=1Ypklog2pk

信息增益:
G a i n ( D , a ) = E n t ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t ( D v ) \mathrm{Gain}(D, a) = \mathrm{Ent}(D) - \sum^{V}_{v=1} \frac{\vert D^v \vert}{\vert D \vert} \mathrm{Ent}(D^v) Gain(D,a)=Ent(D)v=1VDDvEnt(Dv)

计算信息熵时约定:若 p = 0 p = 0 p=0,则 p log ⁡ 2 p = 0 p \log_2p = 0 plog2p=0

def information_entropy(labels_in_node):
    '''
    求当前结点的信息熵
    
    Parameter
    ----------
    labels_in_node: np.ndarray, 如[-1, 1, -1, 1, 1]
    
    Returns
    ----------
    float: information entropy
    '''
    # 统计样本总个数
    num_of_samples = labels_in_node.shape[0]
    
    if num_of_samples == 0:
        return 0
    
    # 统计出标记为1的个数
    num_of_positive = len(labels_in_node[labels_in_node == 1])
    
    # 统计出标记为-1的个数
    num_of_negative = len(labels_in_node[labels_in_node == -1])
    
    # 统计正例的概率
    prob_positive = num_of_positive / num_of_samples
    
    # 统计负例的概率
    prob_negative = num_of_negative / num_of_samples
    
    if prob_positive == 0:
        positive_part = 0
    else:
        positive_part = prob_positive * np.log2(prob_positive)
    
    if prob_negative == 0:
        negative_part = 0
    else:
        negative_part = prob_negative * np.log2(prob_negative)
    
    return - ( positive_part + negative_part )

下面是6个测试样例

# 信息熵测试样例1
example_labels = np.array([-1, -1, 1, 1, 1])
print(information_entropy(example_labels)) # 0.97095

# 信息熵测试样例2
example_labels = np.array([-1, -1, 1, 1, 1, 1, 1])
print(information_entropy(example_labels)) # 0.86312
    
# 信息熵测试样例3
example_labels = np.array([-1, -1, -1, -1, -1, 1, 1])
print(information_entropy(example_labels)) # 0.86312

# 信息熵测试样例4
example_labels = np.array([-1] * 9 + [1] * 8)
print(information_entropy(example_labels)) # 0.99750

# 信息熵测试样例5
example_labels = np.array([1] * 8)
print(information_entropy(example_labels)) # 0

# 信息熵测试样例6
example_labels = np.array([])
print(information_entropy(example_labels)) # 0

接下来完成计算所有特征的信息增益的函数
需要填写三个部分

def compute_information_gains(data, features, target, annotate = False):
    '''
    计算所有特征的信息增益
    
    Parameter
    ----------
        data: pd.DataFrame,传入的样本,带有特征和标记的dataframe
        
        features: list(str),特征名组成的list
        
        target: str, 标记(label)的名字
        
        annotate, boolean,是否打印所有特征的信息增益值,默认为False
        
    Returns
    ----------
        information_gains: dict, key: str, 特征名
                                 value: float,信息增益
    '''
    
    # 我们将每个特征划分的信息增益值存储在一个dict中
    # 键是特征名,值是信息增益值
    information_gains = dict()
    
    # 对所有的特征进行遍历,使用信息增益对每个特征进行计算
    for feature in features:
        
        # 左子树保证所有的样本的这个特征取值为0
        left_split_target = data[data[feature] == 0][target]
        
        # 右子树保证所有的样本的这个特征取值为1
        right_split_target =  data[data[feature] == 1][target]
            
        # 计算左子树的信息熵
        left_entropy = information_entropy(left_split_target)
        
        # 计算左子树的权重
        left_weight = len(left_split_target) / (len(left_split_target) + len(right_split_target))

        # 计算右子树的信息熵
        right_entropy = information_entropy(right_split_target)
        
        # 计算右子树的权重
        right_weight = len(right_split_target) / (len(left_split_target) + len(right_split_target))
        
        # 计算当前结点的信息熵
        current_entropy = information_entropy(data[target])
            
        # 计算使用当前特征划分的信息增益
        gain = current_entropy - (left_weight * left_entropy + right_weight * right_entropy)

        
        # 将特征名与增益值以键值对的形式存储在information_gains中
        information_gains[feature] = gain
        
        if annotate:
            print(" ", feature, gain)
            
    return information_gains
# 信息增益测试样例1
print(compute_information_gains(train_data, one_hot_features, target)['grade_A']) # 0.01759

# 信息增益测试样例2
print(compute_information_gains(train_data, one_hot_features, target)['term_ 60 months']) # 0.01429

# 信息增益测试样例3
print(compute_information_gains(train_data, one_hot_features, target)['grade_B']) # 0.00370

4.2 信息增益率

信息增益率:

G a i n _ r a t i o ( D , a ) = G a i n ( D , a ) I V ( a ) \mathrm{Gain\_ratio}(D, a) = \frac{\mathrm{Gain}(D, a)}{\mathrm{IV}(a)} Gain_ratio(D,a)=IV(a)Gain(D,a)

其中

I V ( a ) = − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ log ⁡ 2 ∣ D v ∣ ∣ D ∣ \mathrm{IV}(a) = - \sum^V_{v=1} \frac{\vert D^v \vert}{\vert D \vert} \log_2 \frac{\vert D^v \vert}{\vert D \vert} IV(a)=v=1VDDvlog2DDv
完成计算所有特征信息增益率的函数
这里要完成五个部分

def compute_information_gain_ratios(data, features, target, annotate = False):
    '''
    计算所有特征的信息增益率并保存起来
    
    Parameter
    ----------
    data: pd.DataFrame, 带有特征和标记的数据
    
    features: list(str),特征名组成的list
    
    target: str, 特征的名字
    
    annotate: boolean, default False,是否打印注释
    
    Returns
    ----------
    gain_ratios: dict, key: str, 特征名
                       value: float,信息增益率
    '''
    
    gain_ratios = dict()
    
    # 对所有的特征进行遍历,使用当前的划分方法对每个特征进行计算
    for feature in features:
        
        # 左子树保证所有的样本的这个特征取值为0
        left_split_target = data[data[feature] == 0][target]
        
        # 右子树保证所有的样本的这个特征取值为1
        right_split_target =  data[data[feature] == 1][target]
            
        # 计算左子树的信息熵
        left_entropy = information_entropy(left_split_target)
        
        # 计算左子树的权重
        left_weight = len(left_split_target) / (len(left_split_target) + len(right_split_target))

        # 计算右子树的信息熵
        right_entropy = information_entropy(right_split_target)
        
        # 计算右子树的权重
        right_weight = len(right_split_target) / (len(left_split_target) + len(right_split_target))
        
        # 计算当前结点的信息熵
        current_entropy = information_entropy(data[target])
        
        # 计算当前结点的信息增益
        
        gain = current_entropy - (left_weight * left_entropy + right_weight * right_entropy)
        
        # 计算IV公式中,当前特征为0的值
        if left_weight == 0:
            left_IV = 0
        else:
            left_IV = - (left_weight * np.log2(left_weight))
        
        # 计算IV公式中,当前特征为1的值
        if right_weight == 0:
            right_IV = 0
        else:
            right_IV = - (right_weight * np.log2(right_weight))
        
        # IV 等于所有子树IV之和的相反数
        IV = - (left_IV + right_IV)
            
        # 计算使用当前特征划分的信息增益率
        # 这里为了防止IV是0,导致除法得到np.inf(无穷),在分母加了一个很小的小数
        gain_ratio = gain / (IV + np.finfo(np.longdouble).eps)
        
        # 信息增益率的存储
        gain_ratios[feature] = gain_ratio
        
        if annotate:
            print(" ", feature, gain_ratio)
            
    return gain_ratios
# 信息增益率测试样例1
print(compute_information_gain_ratios(train_data, one_hot_features, target)['grade_A']) # 0.02573

# 信息增益率测试样例2
print(compute_information_gain_ratios(train_data, one_hot_features, target)['grade_B']) # 0.00417

# 信息增益率测试样例3
print(compute_information_gain_ratios(train_data, one_hot_features, target)['term_ 60 months']) # 0.01970

4.3 基尼指数

数据集 D D D的基尼值:

G i n i ( D ) = ∑ k = 1 ∣ Y ∣ ∑ k ′ ≠ k p k p k ′ = 1 − ∑ k = 1 ∣ Y ∣ p k 2 . \begin{aligned} \mathrm{Gini}(D) & = \sum^{\vert \mathcal{Y} \vert}_{k=1} \sum_{k' \neq k} p_k p_{k'}\\ & = 1 - \sum^{\vert \mathcal{Y} \vert}_{k=1} p^2_k. \end{aligned} Gini(D)=k=1Yk=kpkpk=1k=1Ypk2.

属性 a a a的基尼指数:

G i n i _ i n d e x ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ G i n i ( D v ) \mathrm{Gini\_index}(D, a) = \sum^V_{v = 1} \frac{\vert D^v \vert}{\vert D \vert} \mathrm{Gini}(D^v) Gini_index(D,a)=v=1VDDvGini(Dv)
完成数据集基尼值的计算
这里需要填写三部分

def gini(labels_in_node):
    '''
    计算一个结点内样本的基尼指数
    
    Paramters
    ----------
    label_in_data: np.ndarray, 样本的标记,如[-1, -1, 1, 1, 1]
    
    Returns
    ---------
    gini: float,基尼指数
    '''
    
    # 统计样本总个数
    num_of_samples = labels_in_node.shape[0]
    
    if num_of_samples == 0:
        return 0
    
    # 统计出1的个数
    num_of_positive = len(labels_in_node[labels_in_node == 1])
    
    # 统计出-1的个数
    num_of_negative = len(labels_in_node[labels_in_node == -1])
    
    # 统计正例的概率
    prob_positive = num_of_positive / num_of_samples
    
    # 统计负例的概率
    prob_negative = num_of_negative / num_of_samples
    
    # 计算基尼值
    gini = 1 - (prob_positive ** 2 + prob_negative ** 2)
    
    return gini
# 基尼值测试样例1
example_labels = np.array([-1, -1, 1, 1, 1])
print(gini(example_labels)) # 0.48

# 基尼值测试样例2
example_labels = np.array([-1, -1, 1, 1, 1, 1, 1])
print(gini(example_labels)) # 0.40816
    
# 基尼值测试样例3
example_labels = np.array([-1, -1, -1, -1, -1, 1, 1])
print(gini(example_labels)) # 0.40816

# 基尼值测试样例4
example_labels = np.array([-1] * 9 + [1] * 8)
print(gini(example_labels)) # 0.49827

# 基尼值测试样例5
example_labels = np.array([1] * 8)
print(gini(example_labels)) # 0

# 基尼值测试样例6
example_labels = np.array([])
print(gini(example_labels)) # 0

然后计算所有特征的基尼指数
这里需要填写三部分

def compute_gini_indices(data, features, target, annotate = False):
    '''
    计算使用各个特征进行划分时,各特征的基尼指数
    
    Parameter
    ----------
    data: pd.DataFrame, 带有特征和标记的数据
    
    features: list(str),特征名组成的list
    
    target: str, 特征的名字
    
    annotate: boolean, default False,是否打印注释
    
    Returns
    ----------
    gini_indices: dict, key: str, 特征名
                       value: float,基尼指数
    '''
    
    gini_indices = dict()
    # 对所有的特征进行遍历,使用当前的划分方法对每个特征进行计算
    for feature in features:
        # 左子树保证所有的样本的这个特征取值为0
        left_split_target = data[data[feature] == 0][target]
        
        # 右子树保证所有的样本的这个特征取值为1
        right_split_target =  data[data[feature] == 1][target]
            
        # 计算左子树的基尼值
        left_gini = gini(left_split_target.values)
        
        # 计算左子树的权重
        left_weight = len(left_split_target) / (len(left_split_target) + len(right_split_target))

        # 计算右子树的基尼值
        right_gini = gini(right_split_target.values)
        
        # 计算右子树的权重
        right_weight = len(right_split_target) / (len(left_split_target) + len(right_split_target))
        
        # 计算当前结点的基尼指数
        gini_index = left_weight * left_gini + right_weight * right_gini
        
        # 存储
        gini_indices[feature] = gini_index
        
        if annotate:
            print(" ", feature, gini_index)
            
    return gini_indices
# 基尼指数测试样例1
print(compute_gini_indices(train_data, one_hot_features, target)['grade_A']) # 0.30095

# 基尼指数测试样例2
print(compute_gini_indices(train_data, one_hot_features, target)['grade_B']) # 0.30568

# 基尼指数测试样例3
print(compute_gini_indices(train_data, one_hot_features, target)['term_ 36 months']) # 0.30055

5. 完成最优特征的选择

到此,我们完成了三种划分策略的实现,接下来就是完成获取最优特征的函数
这里需要填写三个部分

def best_splitting_feature(data, features, target, criterion = 'gini', annotate = False):
    '''
    给定划分方法和数据,找到最优的划分特征
    
    Parameters
    ----------
    data: pd.DataFrame, 带有特征和标记的数据
    
    features: list(str),特征名组成的list
    
    target: str, 特征的名字
    
    criterion: str, 使用哪种指标,三种选项: 'information_gain', 'gain_ratio', 'gini'
    
    annotate: boolean, default False,是否打印注释
    
    Returns
    ----------
    best_feature: str, 最佳的划分特征的名字
    
    '''
    if criterion == 'information_gain':
        if annotate:
            print('using information gain')
        
        # 得到当前所有特征的信息增益
        information_gains = compute_information_gains(data, features, target, annotate)
    
        # information_gains是一个dict类型的对象,我们要找值最大的那个元素的键是谁
        # 根据这些特征和他们的信息增益,找到最佳的划分特征
        # YOUR CODE HERE
        best_feature = max(information_gains, key=information_gains.get)
        return best_feature

    elif criterion == 'gain_ratio':
        if annotate:
            print('using information gain ratio')
        
        # 得到当前所有特征的信息增益率
        gain_ratios = compute_information_gain_ratios(data, features, target, annotate)
    
        # 根据这些特征和他们的信息增益率,找到最佳的划分特征
        # YOUR CODE HERE
        best_feature = max(gain_ratios,key=gain_ratios.get)

        return best_feature
    
    elif criterion == 'gini':
        if annotate:
            print('using gini')
        
        # 得到当前所有特征的基尼指数
        gini_indices = compute_gini_indices(data, features, target, annotate)
        
        # 根据这些特征和他们的基尼指数,找到最佳的划分特征
        # YOUR CODE HERE
        best_feature = min(gini_indices, key=gini_indices.get)
        return best_feature
    else:
        raise Exception("传入的criterion不合规!", criterion)

6. 判断结点内样本的类别是否为同一类

def intermediate_node_num_mistakes(labels_in_node):
    '''
    求树的结点中,样本数少的那个类的样本有多少,比如输入是[1, 1, -1, -1, 1],返回2
    
    Parameter
    ----------
    labels_in_node: np.ndarray, pd.Series
    
    Returns
    ----------
    int:个数
    
    '''
    # 如果传入的array为空,返回0
    if len(labels_in_node) == 0:
        return 0
    
    # 统计1的个数
    # YOUR CODE HERE
    num_of_one = np.sum(labels_in_node == 1)
    
    # 统计-1的个数
    # YOUR CODE HERE
    num_of_minus_one = np.sum(labels_in_node == -1)
    
    return num_of_one if num_of_minus_one > num_of_one else num_of_minus_one
# 测试样例1
print(intermediate_node_num_mistakes(np.array([1, 1, -1, -1, -1]))) # 2

# 测试样例2
print(intermediate_node_num_mistakes(np.array([]))) # 0

# 测试样例3
print(intermediate_node_num_mistakes(np.array([1]))) # 0

7. 创建叶子结点

def create_leaf(target_values):
    '''
    计算出当前叶子结点的标记是什么,并且将叶子结点信息保存在一个dict中
    
    Parameter:
    ----------
    target_values: pd.Series, 当前叶子结点内样本的标记

    Returns:
    ----------
    leaf: dict,表示一个叶结点,
            leaf['splitting_features'], None,叶结点不需要划分特征
            leaf['left'], None,叶结点没有左子树
            leaf['right'], None,叶结点没有右子树
            leaf['is_leaf'], True, 是否是叶子结点
            leaf['prediction'], int, 表示该叶子结点的预测值
    '''
    # 创建叶子结点
    leaf = {'splitting_feature' : None,
            'left' : None,
            'right' : None,
            'is_leaf': True}
   
    # 数结点内-1和+1的个数
    num_ones = len(target_values[target_values == +1])
    num_minus_ones = len(target_values[target_values == -1])    

    # 叶子结点的标记使用少数服从多数的原则,为样本数多的那类的标记,保存在 leaf['prediction']
    if num_ones > num_minus_ones:
        leaf['prediction'] = 1
    else:
        leaf['prediction'] = -1

    # 返回叶子结点
    return leaf

8. 递归地创建决策树

递归的创建决策树
递归算法终止的三个条件:

  1. 如果结点内所有的样本的标记都相同,该结点就不需要再继续划分,直接做叶子结点即可
  2. 如果结点所有的特征都已经在之前使用过了,在当前结点无剩余特征可供划分样本,该结点直接做叶子结点
  3. 如果当前结点的深度已经达到了我们限制的树的最大深度,直接做叶子结点
def decision_tree_create(data, features, target, criterion = 'gini', current_depth = 0, max_depth = 10, annotate = False):
    '''
    Parameter:
    ----------
    data: pd.DataFrame, 数据

    features: iterable, 特征组成的可迭代对象,比如一个list

    target: str, 标记的名字

    criterion: 'str', 特征划分方法,只支持三种:'information_gain', 'gain_ratio', 'gini'

    current_depth: int, 当前深度,递归的时候需要记录

    max_depth: int, 树的最大深度,我们设定的树的最大深度,达到最大深度需要终止递归

    Returns:
    ----------
    dict, dict['is_leaf']          : False, 当前顶点不是叶子结点
          dict['prediction']       : None, 不是叶子结点就没有预测值
          dict['splitting_feature']: splitting_feature, 当前结点是使用哪个特征进行划分的
          dict['left']             : dict
          dict['right']            : dict
    '''
    
    if criterion not in ['information_gain', 'gain_ratio', 'gini']:
        raise Exception("传入的criterion不合规!", criterion)
    
    # 复制一份特征,存储起来,每使用一个特征进行划分,我们就删除一个
    remaining_features = features[:]
    
    # 取出标记值
    target_values = data[target]
    if annotate:
        print("-" * 50)
        print("Subtree, depth = %s (%s data points)." % (current_depth, len(target_values)))

    # 终止条件1
    # 如果当前结点内所有样本同属一类,即这个结点中,各类别样本数最小的那个等于0
    # 使用前面写的intermediate_node_num_mistakes来完成这个判断
    # YOUR CODE HERE
    if intermediate_node_num_mistakes(target_values) == 0:
        if annotate:
            print("Stopping condition 1 reached.")
        return create_leaf(target_values)   # 创建叶子结点
    
    # 终止条件2
    # 如果已经没有剩余的特征可供分割,即remaining_features为空
    
    # YOUR CODE HERE
    if not remaining_features:
        if annotate:
            print("Stopping condition 2 reached.")
        return create_leaf(target_values)   # 创建叶子结点
    
    # 终止条件3
    # 如果已经到达了我们要求的最大深度,即当前深度达到了最大深度
    
    # YOUR CODE HERE
    if current_depth == max_depth:
        if annotate:
            print("Reached maximum depth. Stopping for now.")
        return create_leaf(target_values)   # 创建叶子结点

    # 找到最优划分特征
    # 使用best_splitting_feature这个函数
    
    # YOUR CODE HERE
    splitting_feature = best_splitting_feature(data, remaining_features, target, criterion, annotate)
    # 使用我们找到的最优特征将数据划分成两份
    # 左子树的数据
    left_split = data[data[splitting_feature] == 0]
    
    # 右子树的数据
    # YOUR CODE HERE
    right_split = data[data[splitting_feature] == 1]
    # 现在已经完成划分,我们要从剩余特征中删除掉当前这个特征
    remaining_features.remove(splitting_feature)
    
    # 打印当前划分使用的特征,打印左子树样本个数,右子树样本个数
    if annotate:
        print("Split on feature %s. (%s, %s)" % (\
                          splitting_feature, len(left_split), len(right_split)))
        
    # 如果使用当前的特征,将所有的样本都划分到一棵子树中,那么就直接将这棵子树变成叶子结点
    # 判断左子树是不是“完美”的
    if len(left_split) == len(data):
        if annotate:
            print("Creating leaf node.")
        return create_leaf(left_split[target])
    
    # 判断右子树是不是“完美”的
    if len(right_split) == len(data):
        if annotate:
            print("Creating right node.")
        return create_leaf(right_split[target])
        
    # 递归地创建左子树
    left_tree = decision_tree_create(left_split, remaining_features, target, criterion, current_depth + 1, max_depth, annotate)
    
    # 递归地创建右子树
    right_tree = decision_tree_create(right_split, remaining_features, target, criterion, current_depth + 1, max_depth, annotate)                         # YOUR CODE HERE

    # 返回树的非叶子结点
    return {'is_leaf'          : False, 
            'prediction'       : None,
            'splitting_feature': splitting_feature,
            'left'             : left_tree, 
            'right'            : right_tree}

训练一个模型

my_decision_tree = decision_tree_create(train_data, one_hot_features, target, 'gini', max_depth = 6, annotate = False)

9. 预测

接下来我们需要完成预测函数

def classify(tree, x, annotate = False):
    '''
    递归的进行预测,一次只能预测一个样本
    
    Parameters
    ----------
    tree: dict
    
    x: pd.Series,待预测的样本
    
    annotate: boolean, 是否显示注释
    
    Returns
    ----------
    返回预测的标记
    '''
    if tree['is_leaf']:
        if annotate:
            print ("At leaf, predicting %s" % tree['prediction'])
        return tree['prediction']
    else:
        split_feature_value = x[tree['splitting_feature']]
        if annotate:
             print ("Split on %s = %s" % (tree['splitting_feature'], split_feature_value))
        if split_feature_value == 0:
            return classify(tree['left'], x, annotate)
        else:
            return classify(tree['right'], x, annotate)

我们取测试集第一个样本来测试

test_sample = test_data.iloc[0]
print(test_sample)
print('True class: %s ' % (test_sample['safe_loans']))
print('Predicted class: %s ' % classify(my_decision_tree, test_sample))

打印出使用决策树判断的过程

classify(my_decision_tree, test_sample, annotate=True)

10. 在测试集上对我们的模型进行评估

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score

先来编写一个批量预测的函数,传入的是整个测试集那样的pd.DataFrame,这个函数返回一个np.ndarray,存储模型的预测结果
这里需要填写一个部分

def predict(tree, data):
    '''
    按行遍历data,对每个样本进行预测,将值存在prediction中,最后返回np.ndarray
    
    Parameter
    ----------
    tree: dict, 模型
    
    data: pd.DataFrame, 数据
    
    Returns
    ----------
    predictions:np.ndarray, 模型对这些样本的预测结果
    '''
    predictions = np.zeros(len(data)) # 长度和data一样
    
    # YOUR CODE HERE
    for i in range(len(data)):
        predictions[i] = classify(tree,data.iloc[i])
    
    return predictions

11. 请你计算使用不同评价指标得到模型的四项指标的值,填写在下方表格内

树的最大深度为6

# YOUR CODE HERE
criteria = ['information_gain', 'gain_ratio', 'gini']
for c in criteria:
    print(f'Using criterion: {c}')
    my_decision_tree=decision_tree_create(train_data, one_hot_features, target, c, max_depth=6, annotate=False)
    predictions = predict(my_decision_tree, test_data)
    acc33 = accuracy_score(test_data[target], predictions)
    precision33 = precision_score(test_data[target], predictions, average='macro')
    recall33 = recall_score(test_data[target], predictions, average='macro')
    f133 = f1_score(test_data[target], predictions, average='macro')
    print(f'Accuracy: {acc33}\nPrecision: {precision33}\nRecall: {recall33}\nF1 Score: {f133}\n')
    

实验3.4随机森林的应用——鸢尾花分类

加载sklearn中的鸢尾花数据集,选取前两个特征作为分类依据

运用Accuracy, Precision, Recall, F1四个指标进行评测

可视化分类结果

import sklearn
import numpy as np

1.导入数据

from sklearn.datasets import load_iris

feat,label = load_iris(return_X_y=True)
data = load_iris()
feat_names = data['feature_names']
label_names = data['target_names']
print(feat_names)
print(label_names)

选取前两个特征

feat = feat[:,:2]
feat.shape

2.导入模型

from sklearn.ensemble import RandomForestClassifier

3.模型训练

# YOUR CODE HERE
from sklearn.model_selection import train_test_split
# 拆分训练集, 测试集
feat_train, feat_test, label_train, label_test = train_test_split(feat, label, test_size=0.2, random_state=42)
# 创建随机森林分类器
rf_classifier34 = RandomForestClassifier(n_estimators=100, random_state=42)
# 拟合模型
rf_classifier34.fit(feat_train, label_train)
# 进行预测
label_pred = rf_classifier34.predict(feat_test)

4.评价指标的计算

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
# YOUR CODE HERE
acc34 = accuracy_score(label_test, label_pred)
precision34 = precision_score(label_test, label_pred, average='macro')
recall34 = recall_score(label_test, label_pred, average='macro')
f134 = f1_score(label_test, label_pred, average='macro')
print(f'Accuracy: {acc34}\nPrecision: {precision34}\nRecall: {recall34}\nF1 Score: {f134}\n')

5.可视化分类结果

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

# 创建一个网格,用于绘制决策边界
x_min, x_max = feat[:, 0].min() - 1, feat[:, 0].max() + 1
y_min, y_max = feat[:, 1].min() - 1, feat[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01))

# 预测网格上的点的类别
Z = rf_classifier34.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

cmap_background = ListedColormap(['#FFAAAA', '#AAAAFF', '#AAFFAA'])
cmap_points = ListedColormap(['#FF0000', '#0000FF', '#00FF00'])

# 绘制决策边界
plt.contourf(xx, yy, Z, cmap=cmap_background, alpha=0.3)

# 绘制数据点
plt.scatter(feat_test[:, 0], feat_test[:, 1], c=label_test, cmap=cmap_points, edgecolors='k', marker='o', s=80)

# 设置图形属性
plt.title('Random Forest Classifier - Iris Dataset')
plt.xlabel(feat_names[0])
plt.ylabel(feat_names[1])

# 显示图例
legend_labels = [f'{label_names[i]} ({i})' for i in range(len(label_names))]
plt.legend(legend_labels)

# 显示图形
plt.show()

实验3.5自行实现AdaBoost并完成肿瘤分类

加载sklearn中的肿瘤归类数据集

自行选择基学习器(可以使用Scikit-learn现成的分类器)自己实现,使用不同的基学习器实现2种以上的AdaBoost

运用Accuracy, Precision, Recall, F1四个指标进行对比评测,随机选择70%作为训练集,30%作为测试集,把结果绘制成表格

与Scikit-learn 的AdaBoostClassifier得到的结果进行对比(基学习器和你自己实现的AdaBoost相同)

import sklearn
import numpy as np

导入数据

from sklearn.datasets import load_breast_cancer

feat,label = load_breast_cancer(return_X_y=True)

feat.shape

划分数据集:70%训练集,30%测试集 (随机种子固定为32)

from sklearn.model_selection import train_test_split
trainX, testX, trainY, testY = train_test_split(feat, label, test_size = 0.3, random_state = 32)
trainX.shape

实现AdaBoost

import copy
# YOUR CODE HERE
class MyAdaBoostClassifier:
    def __init__(self, base_estimator, n_estimators=50, learning_rate=1.0, n_classes=2):
        self.base_estimator = base_estimator
        self.n_estimators = n_estimators 
        self.lr = learning_rate
        self.R = n_classes
        self.estimators = []
        self.alphas = []  # model_weight
        for m in range(n_estimators):
            self.estimators.append(copy.deepcopy(base_estimator))

    def fit(self, X, y):
        sample_weight = np.ones(len(X)) / len(X)  # 初始化样本权重为 1/N
        for i in range(self.n_estimators):
            model = self.estimators[i]
            model.fit(X, y, sample_weight)  # 训练弱学习器
            y_pred = model.predict(X)
            error = np.sum(sample_weight* (y_pred != y))  
            alpha = self.lr * (np.log((1-error)/error) + np.log(self.R-1))  # 权重系数
            sample_weight *= np.exp(alpha*(y_pred!=y))  # 更新迭代样本权重
            sample_weight /= np.sum(sample_weight)  # 样本权重归一化
            self.alphas.append(alpha)
        return self   
   
    def predict(self, X):  # 假定类别映射成 0,1,...
        y_pred = [] 
        for i in range(self.n_estimators):
            y_pred.append(self.estimators[i].predict_proba(X) )
        # 将预测类别概率与训练权重乘积作为集成预测类别概率    
        y_pred = np.average(np.asarray(y_pred), weights=np.array(self.alphas), axis=0 ) 
        y_pred = y_pred/np.array(self.alphas).sum()
        y_pred = np.argmax(y_pred, axis=1)
        return y_pred

基分类器选择决策树

from sklearn.tree import DecisionTreeClassifier
# YOUR CODE HERE
base_tree = DecisionTreeClassifier(max_depth=1)  # You can customize the base estimator
Mymodel1 = MyAdaBoostClassifier(base_estimator=base_tree, n_estimators=50, learning_rate=1.0)
Mymodel1.fit(trainX, trainY)

基分类器选择对数几率回归

from sklearn.linear_model import LogisticRegression
# YOUR CODE HERE
base_lr = LogisticRegression() 
Mymodel2 = MyAdaBoostClassifier(base_estimator=base_lr, n_estimators=50, learning_rate=1.0)
Mymodel2.fit(trainX, trainY)

评价指标的计算

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
prediction1 = Mymodel1.predict(testX)
prediction2 = Mymodel2.predict(testX)
# YOUR CODE HERE
acc351 = accuracy_score(testY, prediction1)
precision351 = precision_score(testY, prediction1)
recall351 = recall_score(testY, prediction1)
f1351 = f1_score(testY, prediction1)
print(f'Accuracy: {acc351}\nPrecision: {precision351}\nRecall: {recall351}\nF1 Score: {f1351}\n')
acc352 = accuracy_score(testY, prediction2)
precision352 = precision_score(testY, prediction2)
recall352 = recall_score(testY, prediction2)
f1352 = f1_score(testY, prediction2)
print(f'Accuracy: {acc352}\nPrecision: {precision352}\nRecall: {recall352}\nF1 Score: {f1352}\n')

调用sklearn的模型

from sklearn.ensemble import AdaBoostClassifier
# YOUR CODE HERE
# 决策树作为基
base_classifier = DecisionTreeClassifier(max_depth=1)  
ada_boost_model = AdaBoostClassifier(base_classifier, n_estimators=50, learning_rate=1.0)
ada_boost_model.fit(trainX, trainY)

# 预测
predictions353 = ada_boost_model.predict(testX)

# 计算评估指标
acc353 = accuracy_score(testY, predictions353)
precision353 = precision_score(testY, predictions353)
recall353 = recall_score(testY, predictions353)
f1353 = f1_score(testY, predictions353)
print(f'Accuracy: {acc353}\nPrecision: {precision353}\nRecall: {recall353}\nF1 Score: {f1353}\n')

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【云原生运维问题记录】kubesphere登录不跳转问题

文章目录 现象问题排查 结论先行:kubesphere-system名称空间下reids宕机重启,会判断是否通过registry-proxy重新拉取镜像,该镜像原本是通过阿里云上拉取,代理上没有出现超时情况,导致失败。解决方案:删除re…

WordPress从入门到精通【安装部署】

初识WordPress WordPress,简称WP,其简称的由来是取英文单词“word”与“press”的首字母 WP中文官网 1WP主站(英文) 官方标称,已有43%的网站在使用WordPress WordPress亮点 WP使用PHP语言开发,兼容性极…

【Java程序设计】【C00248】基于Springboot的摄影跟拍预定管理系统(有论文)

基于Springboot的摄影跟拍预定管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的摄影跟拍预定管理系统 本系统分为系统功能模块、管理员功能模块、摄影师功能模块以及用户功能模块。 系统功能模块&#xf…

SpringMVC精简知识点

SpringMVC 数据格式化基本数据类型和字符串自动转换特殊数据类型和字符串自动转换 验证及国际化应用实例注意事项和使用细节注解的结合使用数据类型转换校验核心类-DatBinder取消某个属性的绑定中文乱码解决处理json和HttpMessageConverter<T>作业布置SpringMVC文件上传自…

Sklearn、TensorFlow 与 Keras 机器学习实用指南第三版(四)

原文&#xff1a;Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第二部分&#xff1a;神经网络和深度学习 第十章&#xff1a;使用 Keras 入门人工神经网络 鸟类启发我们飞行&#xff0c;牛蒡植…

Qt PCL学习(一):环境搭建

参考 (QT配置pcl)PCL1.12.1QT5.15.2vs2019cmake3.22.4vtk9.1.0visual studio2019Qt5.15.2PCL1.12.1vtk9.1.0cmake3.22.2 本博客用到的所有资源 版本一览&#xff1a;Visual Studio 2019 Qt 5.15.2 PCL 1.12.1 VTK 9.1.0https://pan.baidu.com/s/1xW7xCdR5QzgS1_d1NeIZpQ?pw…

【CSS + ElementUI】更改 el-carousel 指示器样式且隐藏左右箭头

需求 前三条数据以走马灯形式展现&#xff0c;指示器 hover 时可以切换到对应内容 实现 <template><div v-loading"latestLoading"><div class"upload-first" v-show"latestThreeList.length > 0"><el-carousel ind…

2024-2-4-复习作业

源代码&#xff1a; #include <stdio.h> #include <stdlib.h> typedef int datatype; typedef struct Node {datatype data;struct Node *next;struct Node *prev; }*DoubleLinkList;DoubleLinkList create() {DoubleLinkList s(DoubleLinkList)malloc(sizeof(st…

Docker进阶篇-轻量级可视化工具Portainer

一、简介 Portainer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环 境和集群环境。 Portainer分为开源社区版&#xff08;CE版&#xff09;和商用版&#xff08;BE版/EE版&#xff09;。 官网&#xff1a;P…

LeetCode:2.两数相加

目录 题目&#xff1a;​编辑2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 分析问题&#xff1a; 官方的优秀代码博主的注释&#xff1a; 博主的辣眼代码&#xff0c;无注释&#xff0c;拉出来拷打自己&#xff1a; 每日表情包&#xff1a; 2. 两数相加 - 力扣&am…

深度学习-随机梯度下降

在训练过程中使用随机梯度下降&#xff0c;但没有解释它为什么起作用。为了澄清这一点&#xff0c;将继续更详细地说明随机梯度下降&#xff08;stochastic gradient descent&#xff09;。 %matplotlib inline import math from mxnet import np, npx from d2l import mxnet …

C# CAD界面-自定义工具栏(二)

运行环境 vs2022 c# cad2016 调试成功 一、引用 acdbmgd.dllacmgd.dllaccoremgd.dllAutodesk.AutoCAD.Interop.Common.dllAutodesk.AutoCAD.Interop.dll using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.T…

RK3568平台 设备模型基本框架-kobject 和kset

一.什么是设备模型 字符设备驱动通常适用于相对简单的设备&#xff0c;对于一些更复杂的功能&#xff0c;比如说电源管理和热插拔事件管理&#xff0c;使用字符设备框架可能不够灵活和高效。为了应对更复杂的设备和功能&#xff0c;Linux内核提供了设备模型。设备模型允许开发…

西瓜书学习笔记——流形学习(公式推导+举例应用)

文章目录 等度量映射&#xff08;仅保留点与其邻近点的距离&#xff09;算法介绍实验分析 局部线性嵌入&#xff08;不仅保留点与其邻近点的距离还要保留邻近关系&#xff09;算法介绍实验分析 等度量映射&#xff08;仅保留点与其邻近点的距离&#xff09; 算法介绍 等度量映…

Unity动画循环偏移的使用

最近项目中有一个需求是做煤矿中猴车的动画&#xff0c;动画本身不复杂&#xff0c;但是猴车很多&#xff0c;怎么能简化工作量呢&#xff1f; 首先单个猴车的动画循环是必须要做的&#xff0c;重点是怎么让不同的猴车动画按顺序错开&#xff0c;研究了以下&#xff0c;可以通过…

后端登录校验

文章目录 登录校验CookieSessionJWT生成JWT校验JWT基于JWT进行身份验证CSRF Cookie、Session、Token的区别&#xff1f;过滤器(Filter)配置过滤器过滤器链 登录校验 由于HTTP协议是无状态的&#xff0c;我们在进行登录后等一系列接口请求是无法直接区分是哪一个用户的发给服务…

电路设计(10)——超温报警电路的proteus仿真

1.题目背景 在现实生活中&#xff0c;常有一种工程技术&#xff0c;即带有自动温度补偿的设备&#xff0c;能在规定温度内正常工作。但是为了设备安全&#xff0c;需设定工作的上限温度&#xff0c;万一温控补偿失效&#xff0c;设备温度一旦超出上限温度时&#xff0c;便立即切…

ES高可用架构涉及常用功能整理

ES高可用架构涉及常用功能整理 1. es的高可用系统架构和相关组件2. es的核心参数2.1 常规配置2.2 特殊优化配置2.2.1 数据分片按ip打散2.2.2 数据分片机架感知2.2.3 强制要求数据分片机架感知2.2.4 写入线程池优化2.2.5 分片balance优化2.2.6 限流控制器优化 3. es常用命令3.1 …

项目中将sass更换成less(TypeError: this.getOptions is not a function已解决)

在更换之前&#xff0c;首先了解sass与less在用法上的区别有哪些&#xff08;这里简单提几个&#xff09;&#xff1a; 变量区别&#xff1a;Less中用&#xff0c;Sass用$sass支持条件语句&#xff0c;可以使用if{}else{}、for循环等&#xff0c;而less不支持在定义变量时候&a…

PyTorch 2.2 中文官方教程(十八)

开始使用完全分片数据并行&#xff08;FSDP&#xff09; 原文&#xff1a;pytorch.org/tutorials/intermediate/FSDP_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Hamid Shojanazeri&#xff0c;Yanli Zhao&#xff0c;Shen Li 注意…