关于sklearn决策树手动指定节点进行剪枝调整的实现

news2025/3/15 19:09:22

一、决策树剪枝


        决策树的剪枝方式有两种,预剪枝和后剪枝,后剪枝在python的sklearn方法中提供了CCP代价复杂度剪枝法(Cost Complexity Pruning)具体实现代码如下:
 

 # -*- coding: utf-8 -*-
from sklearn.datasets import load_iris
from sklearn import tree
import numpy as np
 
#--------数据准备-----------------------------------
iris = load_iris()                          # 加载数据
X = iris.data
y = iris.target
#-------模型训练---------------------------------
clf = tree.DecisionTreeClassifier(min_samples_split=10,random_state=0,ccp_alpha=0)        
clf = clf.fit(X, y)     
#-------计算ccp路径------------------------------
pruning_path = clf.cost_complexity_pruning_path(X, y)
 
#-------打印结果---------------------------------   
print("\n====CCP路径=================")
print("ccp_alphas:",pruning_path['ccp_alphas'])
print("impurities:",pruning_path['impurities'])    
 
#------设置alpha对树后剪枝-----------------------
clf = tree.DecisionTreeClassifier(min_samples_split=10,random_state=0,ccp_alpha=0.1)        
clf = clf.fit(X, y) 
#------自行计算树纯度以验证-----------------------
is_leaf =clf.tree_.children_left ==-1
tree_impurities = (clf.tree_.impurity[is_leaf]* clf.tree_.n_node_samples[is_leaf]/len(y)).sum()
#-------打印结果--------------------------- 
print("\n==设置alpha=0.1剪枝后的树纯度:=========\n",tree_impurities)

该方法在树构建完成后,对树进行剪枝简化,使以下损失函数最小化。但具体裁剪哪些分枝的是不知道,因此需要一个方法,可以对具体分枝进行裁剪。目前sklearn并没有提供该方法,从源码上进行修改。

二、决策树源码分析

        在github上下载scikit-learn-1.1.X的源码,决策树的实现在scikit-learn-1.1.X/sklearn/tree/_tree.pyx,采用cpython是实现代码分析如下:

#CCP 剪枝方式
def _build_pruned_tree_ccp(
    Tree tree, # OUT
    Tree orig_tree,
    DOUBLE_t ccp_alpha):
    """Build a pruned tree from the original tree using cost complexity
    pruning.

    The values and nodes from the original tree are copied into the pruned
    tree.

    Parameters
    ----------
    tree : Tree
        Location to place the pruned tree
    orig_tree : Tree
        Original tree
    ccp_alpha : positive double
        Complexity parameter. The subtree with the largest cost complexity
        that is smaller than ``ccp_alpha`` will be chosen. By default,
        no pruning is performed.
    """

    cdef:
        SIZE_t n_nodes = orig_tree.node_count
        unsigned char[:] leaves_in_subtree = np.zeros(
            shape=n_nodes, dtype=np.uint8)

    pruning_controller = _AlphaPruner(ccp_alpha=ccp_alpha)

    # CCP方法用于计算哪些节点需要剪枝
    _cost_complexity_prune(leaves_in_subtree, orig_tree, pruning_controller)

    # 实现剪枝的方法
    _build_pruned_tree(tree, orig_tree, leaves_in_subtree,
                       pruning_controller.capacity)

cdef class _CCPPruneController:
    """Base class used by build_pruned_tree_ccp and ccp_pruning_path
    to control pruning.
    """
    cdef bint stop_pruning(self, DOUBLE_t effective_alpha) nogil:
        """Return 1 to stop pruning and 0 to continue pruning"""
        return 0

    cdef void save_metrics(self, DOUBLE_t effective_alpha,
                           DOUBLE_t subtree_impurities) nogil:
        """Save metrics when pruning"""
        pass

    cdef void after_pruning(self, unsigned char[:] in_subtree) nogil:
        """Called after pruning"""
        pass


cdef class _AlphaPruner(_CCPPruneController):
    """Use alpha to control when to stop pruning."""
    cdef DOUBLE_t ccp_alpha
    cdef SIZE_t capacity

    def __cinit__(self, DOUBLE_t ccp_alpha):
        self.ccp_alpha = ccp_alpha
        self.capacity = 0

    cdef bint stop_pruning(self, DOUBLE_t effective_alpha) nogil:
        # The subtree on the previous iteration has the greatest ccp_alpha
        # less than or equal to self.ccp_alpha
        return self.ccp_alpha < effective_alpha

    cdef void after_pruning(self, unsigned char[:] in_subtree) nogil:
        """Updates the number of leaves in subtree"""
        for i in range(in_subtree.shape[0]):
            if in_subtree[i]:
                self.capacity += 1

cdef struct CostComplexityPruningRecord:
    SIZE_t node_idx
    SIZE_t parent

cdef _cost_complexity_prune(unsigned char[:] leaves_in_subtree, # OUT
                            Tree orig_tree,
                            _CCPPruneController controller):
    """Perform cost complexity pruning.

    This function takes an already grown tree, `orig_tree` and outputs a
    boolean mask `leaves_in_subtree` which are the leaves in the pruned tree.
    During the pruning process, the controller is passed the effective alpha and
    the subtree impurities. Furthermore, the controller signals when to stop
    pruning.

    Parameters
    ----------
    leaves_in_subtree : unsigned char[:]
        Output for leaves of subtree
    orig_tree : Tree
        Original tree
    ccp_controller : _CCPPruneController
        Cost complexity controller
    """

    cdef:
        SIZE_t i
        SIZE_t n_nodes = orig_tree.node_count
        # prior probability using weighted samples
        DOUBLE_t[:] weighted_n_node_samples = orig_tree.weighted_n_node_samples
        DOUBLE_t total_sum_weights = weighted_n_node_samples[0]
        DOUBLE_t[:] impurity = orig_tree.impurity
        # weighted impurity of each node
        DOUBLE_t[:] r_node = np.empty(shape=n_nodes, dtype=np.float64)

        SIZE_t[:] child_l = orig_tree.children_left
        SIZE_t[:] child_r = orig_tree.children_right
        SIZE_t[:] parent = np.zeros(shape=n_nodes, dtype=np.intp)

        stack[CostComplexityPruningRecord] ccp_stack
        CostComplexityPruningRecord stack_record
        int rc = 0
        SIZE_t node_idx
        stack[SIZE_t] node_indices_stack

        SIZE_t[:] n_leaves = np.zeros(shape=n_nodes, dtype=np.intp)
        DOUBLE_t[:] r_branch = np.zeros(shape=n_nodes, dtype=np.float64)
        DOUBLE_t current_r
        SIZE_t leaf_idx
        SIZE_t parent_idx

        # candidate nodes that can be pruned
        unsigned char[:] candidate_nodes = np.zeros(shape=n_nodes,
                                                    dtype=np.uint8)
        # nodes in subtree
        unsigned char[:] in_subtree = np.ones(shape=n_nodes, dtype=np.uint8)
        DOUBLE_t[:] g_node = np.zeros(shape=n_nodes, dtype=np.float64)
        SIZE_t pruned_branch_node_idx
        DOUBLE_t subtree_alpha
        DOUBLE_t effective_alpha
        SIZE_t child_l_idx
        SIZE_t child_r_idx
        SIZE_t n_pruned_leaves
        DOUBLE_t r_diff
        DOUBLE_t max_float64 = np.finfo(np.float64).max

    # find parent node ids and leaves
    with nogil:

        for i in range(r_node.shape[0]):
            r_node[i] = (
                weighted_n_node_samples[i] * impurity[i] / total_sum_weights)

        # Push the root node
        ccp_stack.push({"node_idx": 0, "parent": _TREE_UNDEFINED})

        while not ccp_stack.empty():
            stack_record = ccp_stack.top()
            ccp_stack.pop()

            node_idx = stack_record.node_idx
            parent[node_idx] = stack_record.parent

            if child_l[node_idx] == _TREE_LEAF:
                # ... and child_r[node_idx] == _TREE_LEAF:
                leaves_in_subtree[node_idx] = 1
            else:
                ccp_stack.push({"node_idx": child_l[node_idx], "parent": node_idx})
                ccp_stack.push({"node_idx": child_r[node_idx], "parent": node_idx})

        # computes number of leaves in all branches and the overall impurity of
        # the branch. The overall impurity is the sum of r_node in its leaves.
        for leaf_idx in range(leaves_in_subtree.shape[0]):
            if not leaves_in_subtree[leaf_idx]:
                continue
            r_branch[leaf_idx] = r_node[leaf_idx]

            # bubble up values to ancestor nodes
            current_r = r_node[leaf_idx]
            while leaf_idx != 0:
                parent_idx = parent[leaf_idx]
                r_branch[parent_idx] += current_r
                n_leaves[parent_idx] += 1
                leaf_idx = parent_idx

        for i in range(leaves_in_subtree.shape[0]):
            candidate_nodes[i] = not leaves_in_subtree[i]

        # save metrics before pruning
        controller.save_metrics(0.0, r_branch[0])

        # while root node is not a leaf
        while candidate_nodes[0]:

            # computes ccp_alpha for subtrees and finds the minimal alpha
            effective_alpha = max_float64
            for i in range(n_nodes):
                if not candidate_nodes[i]:
                    continue
                subtree_alpha = (r_node[i] - r_branch[i]) / (n_leaves[i] - 1)
                if subtree_alpha < effective_alpha:
                    effective_alpha = subtree_alpha
                    pruned_branch_node_idx = i

            if controller.stop_pruning(effective_alpha):
                break

            node_indices_stack.push(pruned_branch_node_idx)

            # descendants of branch are not in subtree
            while not node_indices_stack.empty():
                node_idx = node_indices_stack.top()
                node_indices_stack.pop()

                if not in_subtree[node_idx]:
                    continue # branch has already been marked for pruning
                candidate_nodes[node_idx] = 0
                leaves_in_subtree[node_idx] = 0
                in_subtree[node_idx] = 0

                if child_l[node_idx] != _TREE_LEAF:
                    # ... and child_r[node_idx] != _TREE_LEAF:
                    node_indices_stack.push(child_l[node_idx])
                    node_indices_stack.push(child_r[node_idx])
            leaves_in_subtree[pruned_branch_node_idx] = 1
            in_subtree[pruned_branch_node_idx] = 1

            # updates number of leaves
            n_pruned_leaves = n_leaves[pruned_branch_node_idx] - 1
            n_leaves[pruned_branch_node_idx] = 0

            # computes the increase in r_branch to bubble up
            r_diff = r_node[pruned_branch_node_idx] - r_branch[pruned_branch_node_idx]
            r_branch[pruned_branch_node_idx] = r_node[pruned_branch_node_idx]

            # bubble up values to ancestors
            node_idx = parent[pruned_branch_node_idx]
            while node_idx != _TREE_UNDEFINED:
                n_leaves[node_idx] -= n_pruned_leaves
                r_branch[node_idx] += r_diff
                node_idx = parent[node_idx]

            controller.save_metrics(effective_alpha, r_branch[0])

        controller.after_pruning(in_subtree)

# 构造对象在下面剪枝使用使用
cdef struct BuildPrunedRecord:
    SIZE_t start
    SIZE_t depth
    SIZE_t parent
    bint is_left

# 剪枝方法,传入需要兼职的节点信息leaves_in_subtree
cdef _build_pruned_tree(
    Tree tree, # 输出树
    Tree orig_tree, # 源树
    const unsigned char[:] leaves_in_subtree,
    SIZE_t capacity):
    """Build a pruned tree.

    Build a pruned tree from the original tree by transforming the nodes in
    ``leaves_in_subtree`` into leaves.

    Parameters
    ----------
    tree : Tree
        Location to place the pruned tree
    orig_tree : Tree
        Original tree
    leaves_in_subtree : unsigned char memoryview, shape=(node_count, )
        Boolean mask for leaves to include in subtree
    capacity : SIZE_t
        Number of nodes to initially allocate in pruned tree
    """
    tree._resize(capacity)

    cdef:
        SIZE_t orig_node_id
        SIZE_t new_node_id
        SIZE_t depth
        SIZE_t parent
        bint is_left
        bint is_leaf

        # value_stride for original tree and new tree are the same
        SIZE_t value_stride = orig_tree.value_stride
        SIZE_t max_depth_seen = -1
        int rc = 0
        Node* node
        double* orig_value_ptr
        double* new_value_ptr

        stack[BuildPrunedRecord] prune_stack
        BuildPrunedRecord stack_record

    with nogil:
        # push root node onto stack
        prune_stack.push({"start": 0, "depth": 0, "parent": _TREE_UNDEFINED, "is_left": 0})

        while not prune_stack.empty():
            stack_record = prune_stack.top()
            prune_stack.pop()

            orig_node_id = stack_record.start
            depth = stack_record.depth
            parent = stack_record.parent
            is_left = stack_record.is_left

            is_leaf = leaves_in_subtree[orig_node_id]
            node = &orig_tree.nodes[orig_node_id]

            new_node_id = tree._add_node(
                parent, is_left, is_leaf, node.feature, node.threshold,
                node.impurity, node.n_node_samples,
                node.weighted_n_node_samples)

            if new_node_id == SIZE_MAX:
                rc = -1
                break

            # copy value from original tree to new tree
            orig_value_ptr = orig_tree.value + value_stride * orig_node_id
            new_value_ptr = tree.value + value_stride * new_node_id
            memcpy(new_value_ptr, orig_value_ptr, sizeof(double) * value_stride)

            if not is_leaf:
                # Push right child on stack
                prune_stack.push({"start": node.right_child, "depth": depth + 1,
                                  "parent": new_node_id, "is_left": 0})
                # push left child on stack
                prune_stack.push({"start": node.left_child, "depth": depth + 1,
                                  "parent": new_node_id, "is_left": 1})

            if depth > max_depth_seen:
                max_depth_seen = depth

        if rc >= 0:
            tree.max_depth = max_depth_seen
    if rc == -1:
        raise MemoryError("pruning tree")

基于CCP的代码,去除CCP的计算,直接指定哪些节点需要剪枝,复用_build_pruned_tree方法,具体剪枝代码如下,实现prune_tree方法:

cdef struct PruningRecord:
    SIZE_t node_idx
    SIZE_t parent
    SIZE_t leaves

def prune_tree(
    Tree tree, # OUT
    Tree orig_tree,
    list leaves_redoces):

    cdef:
        SIZE_t n_nodes = orig_tree.node_count
        unsigned char[:] leaves_in_subtree = np.zeros(shape=n_nodes, dtype=np.uint8)
        stack[PruningRecord] ccp_stack
        PruningRecord stack_record
        SIZE_t[:] child_l = orig_tree.children_left
        SIZE_t[:] child_r = orig_tree.children_right
        SIZE_t capacity = 0
        SIZE_t leaves = 0

    for leaf_idx in leaves_redoces:
        leaves_in_subtree[leaf_idx] = 1
        
    ccp_stack.push({"node_idx": 0, "parent": _TREE_UNDEFINED, "leaves": 0})
    while not ccp_stack.empty():
        stack_record = ccp_stack.top()
        leaves = stack_record.leaves
        ccp_stack.pop()
        node_idx = stack_record.node_idx
        if leaves_in_subtree[node_idx]:
            leaves = leaves_in_subtree[node_idx]
        if child_l[node_idx] != _TREE_LEAF:
            leaves_in_subtree[node_idx] = leaves
            ccp_stack.push({"node_idx": child_l[node_idx], "parent": node_idx, "leaves": leaves})
            ccp_stack.push({"node_idx": child_r[node_idx], "parent": node_idx, "leaves": leaves})
        else:
            leaves_in_subtree[node_idx] = 1
    
    for i in range(leaves_in_subtree.shape[0]):
        if leaves_in_subtree[i]:
            capacity += 1
    _build_pruned_tree(tree, orig_tree, leaves_in_subtree, capacity)

由于是.pyx文件需要通过源码编译生成指定的文件,命令:

python setup.py build_ext --inplace

将目录下sklearn\tree\_tree.cp38-win_amd64.pyd文件复制替换当前python环境下的同名文件,重启测试:

#-*- coding: UTF-8 -*-
'''
Created on 2021年3月4日

@author: xuconghui
'''
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.tree._tree import prune_tree,Tree
import numpy as np
from sklearn.metrics import precision_score,recall_score,accuracy_score,f1_score
import pandas as pd
# 加载Iris数据集
iris = load_iris()

X = iris.data
y = iris.target
feature_names = iris.feature_names
print("特征:"+str(iris.feature_names))
# 创建并训练决策树分类器
tree_classifier = DecisionTreeClassifier(random_state=0)
tree_classifier.fit(X, y)

y_predict = tree_classifier.predict(X)
acc = accuracy_score(y, y_predict)
p_score = precision_score(y, y_predict, average='micro')
r_score = recall_score(y, y_predict, average='micro')
f_score = f1_score(y, y_predict, average='micro')
print("准确率="+str(acc)+" 精确度="+str(p_score)+" 召回度="+str(r_score)+"f_score="+str(f_score))
tree.plot_tree(tree_classifier,filled=True)
plt.show()
# 手动剪枝决策树
def xprune_tree(tree_model, recodes=[7]):
    feature_idx = feature_names.index(feature_name)
    feature_idxs = [feature_idx,feature_idx-len(feature_names)]
    pruned_tree = Tree(tree_model.n_features_in_, tree_model.classes_, tree_model.n_outputs_)
    prune_tree(pruned_tree,tree_model.tree_,recodes)
    tree_model.tree_ = pruned_tree


xprune_tree(tree_classifier)

# 输出
with open(iris.dot", 'w') as f:
    tree.export_graphviz(tree_classifier, out_file=f)
tree.plot_tree(tree_classifier,filled=True)
plt.show()

决策树如预期的那般被处理了,但是用其他工具没办法显示出来,不知道什么问题,不太懂cpython,需要大神帮忙看一下,目前剪枝后的系数也变化,可以用于预测,计算准确度也可以,pmml也可以导出,原有的决策树功能都保留下来。

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

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

相关文章

Java入门基础学习笔记44——String

为什么要学习String的处理呢&#xff1f; 开发中&#xff0c;对字符串的处理是非常常见的。 String是什么&#xff1f;可以做什么&#xff1f; java.lang.String 代表字符串。可以用来创建对象封装字符串数据&#xff0c;并对其进行处理。 1、创建对象 2、封装字符串数据 3…

超过GPT4.0?Claude3官网及国内镜像站,国内使用克劳德3的方法

近期又有一个大模型横空出世&#xff0c;这就是由Anthropic公司推出的Claude 3&#xff08;克劳德3&#xff09;&#xff0c;在多项基准测试中得分超越了GPT-4&#xff0c;那么他到底是什么情况呐&#xff1f;其实大家在国内也是可以使用上的&#xff01; 克劳德Claude3 关于…

Python 闭包的高级用法详解

所谓闭包&#xff0c;就是指内函数使用了外函数的局部变量&#xff0c;并且外函数把内函数返回出来的过程&#xff0c;这个内函数称之为闭包函数。可以理解为是函数式编程中的封装。 内部函数可以使用外部函数定义的属性&#xff1a;外部函数调用后&#xff0c;返回内部函数的地…

Java入门基础学习笔记36——面向对象基础

面向对象编程快速入门&#xff1a; 计算机是用来处理数据的。 单个变量 数组变量 对象数据 Student类&#xff1a; package cn.ensource.object;public class Student {String name;double chinese_score;double math_score;public void printTotalScore() {System.out.pr…

AUTOMATIC1111/stable-diffusion-webui/stable-diffusion-webui-v1.9.3

配置环境介绍 目前平台集成了 Stable Diffusion WebUI 的官方镜像&#xff0c;该镜像中整合如下资源&#xff1a; GpuMall智算云 | 省钱、好用、弹性。租GPU就上GpuMall,面向AI开发者的GPU云平台 Stable Diffusion WebUI版本&#xff1a;v1.9.3 Python版本&#xff1a;3.10.…

HCIE是什么证书?为什么要考?

每当我发一些关于HCIE的话题时&#xff0c;总有小伙伴过来问“啥是HCIE啊&#xff1f;”今天就一起来了解下&#xff0c;到底什么是HCIE&#xff1f;为什么这么多人都要考HCIE? HCIE是华为认证ICT专家的缩写&#xff0c;它是华为认证体系中最高级别的ICT技术认证。HCIE全称为H…

windows 设置系统字体 (win11 win10)

由于微软的字体是有版权的&#xff0c;所以我打算替换掉 1.下载替换工具 github的项目&#xff0c;看起来很多人对微软默认字体带版权深恶痛绝。 项目地址&#xff1a;nomeiryoUi地址 这里选取最新的版本即可 2.打开软件 这里显示标题栏不能改&#xff0c;确认&#xff0c;其…

使用Systemd 设置Python程序开机启动

在 Linux 系统中设置Python 脚本开机启动&#xff0c;通常可以通过以下几种方式实现&#xff1a; 1. 使用 systemd&#xff08;推荐方式&#xff09; systemd 是大多数现代 Linux 发行版使用的初始化系统和服务管理器。你可以为Python 脚本创建一个 systemd 服务文件&#xf…

鸿蒙ArkUI-X平台差异化:【运行态差异化(@ohos.deviceInfo)】

平台差异化 简介 跨平台使用场景是一套ArkTS代码运行在多个终端设备上&#xff0c;如Android、iOS、OpenHarmony&#xff08;含基于OpenHarmony发行的商业版&#xff0c;如HarmonyOS Next&#xff09;。当不同平台业务逻辑不同&#xff0c;或使用了不支持跨平台的API&#xf…

Android开发-Android开发中的TCP与UDP通信策略的实现

Android 开发中的 TCP 与 UDP 通信策略的实现 1. 前言2. 准备工作3. Kotlin 中 TCP 通信实现客户端代码示例&#xff1a;服务器代码示例&#xff1a; 4. Kotlin 中 UDP 通信实现客户端代码示例&#xff1a;服务器代码示例&#xff1a; 5. TCP 与 UDP 应用场景分析TCP 实现可靠传…

词条唤夜兽唤夜兽的养殖与护理 幻兽帕鲁 唤夜兽怎么获取 唤夜兽去哪里抓 crossover玩Steam游戏

唤夜兽在地图上没有出现&#xff0c;是唤冬兽和雷冥鸟共同培育出来的帕鲁。 ------------------------- 介绍&#xff1a; 帕洛斯群岛之守护神&#xff0c;拥呼唤黑夜之力。 其会于灾厄席捲大地之际腾空而起&#xff0c;唤来无尽暗夜&#xff0c;试图封印灾厄。 ---------…

Video-FocalNets: Spatio-Temporal Focal Modulation for Video Action Recognition

标题&#xff1a;Video-FocalNets&#xff1a;用于视频动作识别的时空聚焦调制 源文链接&#xff1a;Wasim_Video-FocalNets_Spatio-Temporal_Focal_Modulation_for_Video_Action_Recognition_ICCV_2023_paper.pdf (thecvf.com)https://openaccess.thecvf.com/content/ICCV202…

深入解析文华量化交易策略---交易指令如何选择

随着金融投资的迅猛发展&#xff0c;自动化策略模型已逐渐成为现代投资领域的一股重要力量。量化交易模型均以数据为驱动&#xff0c;通过运用数学模型和算法&#xff0c;对期货、黄金等投资市场走势进行精准预测和高效交易。 艾云策略整理了量化策略相关资料&#xff0c;希望通…

从零开始搭建一个SpringBoot项目

目录 Spring BootSpring Boot 项目开发环境1、快速创建SpringBoot项目2、pom.xml 添加 Meavn 依赖3、配置application.yml4、验证数据库是否连接成功5、配置 Druid 数据源 Spring Boot 整合 MyBatis1、准备依赖2、application-dev.yml 配置3、启动类添加Mapper接口扫描器4、设置…

【Python搞定车载自动化测试】——Python基于Pytest框架实现UDS诊断自动化(含Python源码)

系列文章目录 【Python搞定车载自动化测试】系列文章目录汇总 文章目录 系列文章目录&#x1f4af;&#x1f4af;&#x1f4af; 前言&#x1f4af;&#x1f4af;&#x1f4af;一、环境搭建1.软件环境2.硬件环境 二、目录结构三、源码展示1.诊断基础函数方法2.诊断业务函数方法…

09.自注意力机制

文章目录 输入输出运行如何运行解决关联性attention score额外的Q K V Multi-head self-attentionPositional EncodingTruncated Self-attention影像处理vs CNNvs RNN图上的应用 输入 输出 运行 链接&#xff08;Attention Is All You Need&#xff09; 如何运行 解决关联性 a…

Iphone自动化指令每隔固定天数打开闹钟关闭闹钟

1.业务需求&#xff1a;小z每隔五天有一个夜班&#xff0c;然后下午会有三个小时的休息时间&#xff0c;如果闹钟不响就会错过交班日期&#xff0c;但是如果设置闹钟&#xff0c;iPhone的闹钟只能设定固定循环日期闹钟&#xff0c;或者一次的闹钟&#xff0c;导致要么忘记设闹钟…

【网络安全】社会工程学攻击与防范

一、社会工程学概述 1、社会工程学的定义 通过利用人们的心理弱点、本能反应、好奇心、信任、贪婪等一些心理陷阱进行的诸如欺骗、伤害、信息盗取、利益谋取等对社会及人类带来危害的行为或方法。 当网络恶意攻击者无法通过纯粹的计算机技术达到目的时&#xff0c;高超的情商…

【Text2SQL】WikiSQL 数据集与 Seq2SQL 模型

论文&#xff1a;Seq2SQL: Generating Structured Queries from Natural Language using Reinforcement Learning ⭐⭐⭐⭐⭐ ICLR 2018 Dataset: github.com/salesforce/WikiSQL Code&#xff1a;Seq2SQL 模型实现 一、论文速读 本文提出了 Text2SQL 方向的一个经典数据集 —…

Amesim应用篇-电芯等效电路模型标定

前言 为了使计算模型更加准确,在有电芯实验测试数据的情况下,依据现有的实验数据对Amesim中的电池等效电路模型进行标定。标定的目的是为了获得更加符合项目实际情况的电芯等效电路模型,标定完的电芯可以用于搭建PACK模型,也可以用于其他虚拟实验。本文以充电标定为例,进…