Deap 框架细节介绍

news2024/11/25 15:50:40

创建一个 gp.PrimitiveSet 对象,对象名为 MAIN,自变量为 3

pset = gp.PrimitiveSet("MAIN", 3)
print(pset)
<deap.gp.PrimitiveSet object at 0x000001FBE182AB20>

gp.py(均为产生函数集与节点集)

PrimitiveSet

class PrimitiveSet(PrimitiveSetTyped):
    """Class same as :class:`~deap.gp.PrimitiveSetTyped`, except there is no
    definition of type.
    """

    def __init__(self, name, arity, prefix="ARG"): # 此时 name = MAIN, arity = 3,
        # 创建 arity 个类对象,案例中为 3,
        args = [__type__] * arity
        PrimitiveSetTyped.__init__(self, name, args, __type__, prefix)

在这里插入图片描述

PrimitiveSetTyped

class PrimitiveSetTyped(object):
    """Class that contains the primitives that can be used to solve a
    Strongly Typed GP problem. The set also defined the researched
    function return type, and input arguments type and number.
    """

    # name = MAIN,in_types=args(为每个变量创建的类组成的列表), ret_type = __type__(元类)
    def __init__(self, name, in_types, ret_type, prefix="ARG"):
        # 存储终端节点的字典
        self.terminals = defaultdict(list)

        # defaultdict(list) 为默认 value 为 list 的字典
        self.primitives = defaultdict(list) # 后续可通过pset.primitives[pset.ret][i] 依次提取函数, .name 可查看函数名
        self.arguments = []

        # setting "__builtins__" to None avoid the context
        # being polluted by builtins function when evaluating
        # GP expression.
        self.context = {"__builtins__": None}
        self.mapping = dict()

        # 存储终端节点个数
        self.terms_count = 0

        # 存储函数节点个数
        self.prims_count = 0

        # PrimitiveSet 类名
        self.name = name

        self.ret = ret_type # __type__(元类)

        # 自变量集合
        self.ins = in_types
        for i, type_ in enumerate(in_types):
            # 为每个自变量从 0 编号,如这里的 ARG0, ARG1, ARG2
            arg_str = "{prefix}{index}".format(prefix=prefix, index=i)

            # 将 arg_str 添加到 arguments 列表中
            self.arguments.append(arg_str)

            # 将每个自变量转换为终端节点类类型,
            term = Terminal(arg_str, True, type_)

            # 将 term 分为终端节点与函数节点,分别添加到 dict_ 中
            self._add(term)

            # 终端节点数 + 1
            self.terms_count += 1

Terminal

class Terminal(object):
    """Class that encapsulates terminal primitive in expression. Terminals can
    be values or 0-arity functions.
    """
    __slots__ = ('name', 'value', 'ret', 'conv_fct')

    def __init__(self, terminal, symbolic, ret):
        self.ret = ret # 节点类型,__type__
        self.value = terminal # ARG0
        self.name = str(terminal) # 'ARG0'
        self.conv_fct = str if symbolic else repr # 见详解 1 处

_add

def _add(self, prim):
    def addType(dict_, ret_type):
        if ret_type not in dict_:
            new_list = []
            for type_, list_ in list(dict_.items()):
                if issubclass(type_, ret_type):
                    for item in list_:
                        if item not in new_list:
                            new_list.append(item)
            dict_[ret_type] = new_list

    addType(self.primitives, prim.ret) # primitives 函数节点组成的字典,prim.ret 当前传入的节点类型
    addType(self.terminals, prim.ret) # self.terminals,终端节点组成的字典

    self.mapping[prim.name] = prim # prim.name = ARG0

    # 判断 prim 是否为 函数类型,即 Primitive
    if isinstance(prim, Primitive): # isinstance 判断是否为同一类型
        for type_ in prim.args:
            addType(self.primitives, type_)
            addType(self.terminals, type_)
        dict_ = self.primitives
    else:
        # 否则为终端节点类型
        dict_ = self.terminals

    for type_ in dict_:
        if issubclass(prim.ret, type_): # 判断 prim.ret 是否为 type_ 的子类
            dict_[type_].append(prim) # 将 prim 添加到字典 dict_ 中

addPrimitive(PrimitiveSet)

# arity 函数参数个数,如-为2,+为2,log为1,exp为1, ariry=2,name='minus'
def addPrimitive(self, primitive, arity, name=None):
    """Add primitive *primitive* with arity *arity* to the set.
    If a name *name* is provided, it will replace the attribute __name__
    attribute to represent/identify the primitive.
    """
    assert arity > 0, "arity should be >= 1"
    # 参数产生的类的组合,比如这里 - 含有两个参数,则 args = [<class 'object'>, <class 'object'>]
    args = [__type__] * arity
    # primitive:定义的函数,args = [<class 'object'>, <class 'object'>], __type__ = 元类, name='minus'
    PrimitiveSetTyped.addPrimitive(self, primitive, args, __type__, name)

addPrimitive(PrimitiveSetTyped)

# in_types = [<class 'object'>, <class 'object'>], ret_type = __type__(元类)
def addPrimitive(self, primitive, in_types, ret_type, name=None):
    """Add a primitive to the set.

    :param primitive: callable object or a function.
    :parma in_types: list of primitives arguments' type
    :param ret_type: type returned by the primitive.
    :param name: alternative name for the primitive instead
                 of its __name__ attribute.
    """
    if name is None:
    	"""此处设置 name 参数,默认为定义时的函数名,如 def add(int a, int b), 则 name 默认为 add"""
        name = primitive.__name__
    prim = Primitive(name, in_types, ret_type)

    assert name not in self.context or \
           self.context[name] is primitive, \
        "Primitives are required to have a unique name. " \
        "Consider using the argument 'name' to rename your " \
        "second '%s' primitive." % (name,)
    # 判断 prim 是否从未被添加进 _dict 字典中,若没有,则添加进去
    self._add(prim)
    self.context[prim.name] = primitive # 用于表示此名称的节点为函数节点
    self.prims_count += 1 # 函数节点个数 + 1

Primitive

class Primitive(object):
    """Class that encapsulates a primitive and when called with arguments it
    returns the Python code to call the primitive with the arguments.

        >>> pr = Primitive("mul", (int, int), int)
        >>> pr.format(1, 2)
        'mul(1, 2)'
    """
    # 定义实例化此类后能访问的属性,元组以外的属性均不可访问
    __slots__ = ('name', 'arity', 'args', 'ret', 'seq')

    def __init__(self, name, args, ret):
        self.name = name # 函数名,minus
        self.arity = len(args) # 参数个数,2
        self.args = args # 参数个数定义的类组成的集合,[<class 'object'>, <class 'object'>]
        self.ret = ret # 当前类属性 <class 'object'>
        args = ", ".join(map("{{{0}}}".format, list(range(self.arity)))) # 为每个参数编号, args = '{0}, {1}'
        
        # 'minus({0}, {1})'
        self.seq = "{name}({args})".format(name=self.name, args=args)

小技巧

# 在函数集中随便选择一个,
prim = random.choice(pset.primitives[type_]) # type_ = pset.ret

# 在终点集中随机选择一个节点
term = random.choice(pset.terminals[type_])
  • type_ = pset.ret:表示原语集合的类型
  • pset.primitives:函数集,用字典表示
pset.ret # <class 'object'>
pset.primitives # 函数集,字典类型
pset.primitives[pset.ret] # 在字典类型中提取 pset.ret(<class 'object'>),即可得到所有函数集中的函数集合
# 寻找所有函数组成的列表中,函数名 == "add",对应的索引位置,通常会返回一个列表,比如[1], 通过在代码最后加一个[0]提取, 即可得到 1 这个值
index = [primitive_index for primitive_index in range(len(pset.primitives[pset.ret])) if pset.primitives[pset.ret][primitive_index].name == "add"]

提取所有终端节点,返回一个所有终端节点组成的集合

pset.terminals # # 终端集,字典类型
pset.terminals[pset.ret]

提取以 Node 索引对应的节点为根节点的子树

tree=PrimitiveTree(genHalfAndHalf(pset, 1, 3))
for Node in range(len(tree)):
	tree[tree.searchSubtree(Node)] # tree.searchSubtree(Node) 返回的是一个切片 slice

获取函数集中第 i 个加入到函数集中的函数的函数名:

pset.primitives[pset.ret][i].name

所有的自变量组成的列表,[ARG0, ARG1, …]

pset.arguments

详解 1

这是一个Python中的三元表达式(ternary expression),用于根据条件选择不同的表达式。在这个三元表达式中,strrepr是Python中的两个内置函数,分别用于将对象转换为字符串和计算对象的可打印表示。symbolic是一个条件,如果为True,则选择str,否则选择repr

具体来说,这个三元表达式的意义是:

如果symbolic为True,则返回一个字符串表示;否则返回对象的可打印表示。

示例代码:

x = 10
symbolic = True
result = str(x) if symbolic else repr(x)
print(result)  # 输出 '10'

在上面的代码中,由于symbolic为True,所以选择了str(x),即将x转换为字符串'10'。因此,result的值为'10'
如果将symbolic改为False,则会选择repr(x),即返回x的可打印表示:

x = 10
symbolic = False
result = str(x) if symbolic else repr(x)
print(result)  # 输出 '10'

在这个例子中,由于symbolic为False,所以选择了repr(x),即返回x的可打印表示10。因此,result的值为10

终端节点参数:

  • ret:节点的类型
  • value:节点值
  • name:节点名称
  • conv_fct:节点信息显示

整体代码

import random

import numpy
from deap import gp, creator, base, tools


def minus(left,right):
    return numpy.subtract(left,right)

pset = gp.PrimitiveSet("MAIN", 3)
print(pset)

pset.addPrimitive(minus, 2, 'minus')

pset.renameArguments(ARG0='x0')

# 定义terminal set
pset.addTerminal(3)  # 常数
pset.addEphemeralConstant('num',lambda:random.randint(-5,5))  # 随机数:(name,随机数函数)

# 三种生成方法,full,grow,half(primitive set,min_depth,max_depth)
# Deap 框架中树的最大深度是91, 最小深度是0(只有一个叶子节点)
expr1 = gp.genFull(pset, 1, 3)    # list
expr2 = gp.genGrow(pset, 1, 3)
expr3 = gp.genHalfAndHalf(pset, 1, 3)
tree = gp.PrimitiveTree(expr1)  # 将表达式形式转换成树形结构

# 编译表达式:必须经过编译才能进行运算
function1 = gp.compile(tree, pset)
# function2 = gp.compile(expr2,pset)
result = function1(1, 2)   # 输入变量值能够得到该表达式的结果
print('result:', result)

gp.genFull、gp.genGrow、gp.genHalfAndHalf

  • gp.genFull:产生一棵满二叉树,树高等于树的深度时停止产生树,先从函数集中选择,当树高等于树的深度时,再从终端集中进行选择,最终选出的节点顺序存储在列表中。整体为一个类结构:[<deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.num object at 0x0000026F4903C270>, <deap.gp.Terminal object at 0x0000026F49038880>,
  • 注: 三个方法最终返回的都是一个列表,列表依次存储了树形结构的节点
def genFull(pset, min_, max_, type_=None):
    """Generate an expression where each leaf has the same depth
    between *min* and *max*.

    :param pset: Primitive set from which primitives are selected.
    :param min_: Minimum height of the produced trees.
    :param max_: Maximum Height of the produced trees.
    :param type_: The type that should return the tree when called, when
                  :obj:`None` (default) the type of :pset: (pset.ret)
                  is assumed.
    :returns: A full tree with all leaves at the same depth.
    """

    def condition(height, depth): # 终止条件:产生树的节点深度恰好等于树高
        """Expression generation stops when the depth is equal to height."""
        return depth == height

    return generate(pset, min_, max_, condition, type_)

generate

def generate(pset, min_, max_, condition, type_=None):
    """创建一颗树:树中的节点均存储在列表中,当满足 condition 条件时停止.

    :param pset: Primitive set from which primitives are selected.
    :param min_: 产生的树的最小高度
    :param max_: 产生的树的最大高度
    :param condition: The condition is a function that takes two arguments,
                      the height of the tree to build and the current
                      depth in the tree.
    :param type_: 返回树的类型,默认应该为 pset: (pset.ret)

    :returns: A grown tree with leaves at possibly different depths
              depending on the condition function.
    """
    if type_ is None:
        type_ = pset.ret #  pset.ret 为节点类别 <deap.gp.PrimitiveSet object at 0x000001C5DC245160>
    expr = [] # 将在函数集与终端集选出的节点放入到 expr 中
    height = random.randint(min_, max_) # 定义树高:从最小深度与最大深度之间随机选择一个值
    stack = [(0, type_)] # 利用栈结构来产生树结构,初始时深度为 0,节点为 type_ 类型
    while len(stack) != 0:
        depth, type_ = stack.pop()
        if condition(height, depth):
            try:
                # =在终点集中随机选择一个节点
                term = random.choice(pset.terminals[type_])
            except IndexError:
                _, _, traceback = sys.exc_info()
                raise IndexError("The gp.generate function tried to add " \
                                  "a terminal of type '%s', but there is " \
                                  "none available." % (type_,)).with_traceback(traceback)
            if isclass(term): # 需要判断是否为一个类类型
                term = term()
            expr.append(term) # 将选出的终点集添加进去
        else:
            try:
                prim = random.choice(pset.primitives[type_]) # 从函数集中随机选择一个节点
            except IndexError:
                _, _, traceback = sys.exc_info()
                raise IndexError("The gp.generate function tried to add " \
                                  "a primitive of type '%s', but there is " \
                                  "none available." % (type_,)).with_traceback(traceback)
            expr.append(prim) # 将选出的函数添加到 expr 中
            for arg in reversed(prim.args): # 遍历函数参数类
                stack.append((depth + 1, arg)) # 添加到栈中,后续产生更深的树
    return expr # 由许多节点组成的列表

gp.PrimitiveTree(产生树结构)

将:[<deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.num object at 0x0000026F4903C270>, <deap.gp.Terminal object at 0x0000026F49038880>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Terminal object at 0x0000026F49038740>, <deap.gp.Terminal object at 0x0000026F49038880>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Terminal object at 0x0000026F49038740>, <deap.gp.num object at 0x0000026F4903C360>, <deap.gp.Primitive object at 0x0000026F49035D10>, <deap.gp.Terminal object at 0x0000026F49038740>, <deap.gp.Terminal object at 0x0000026F49038740>]

转化为: minus(minus(minus(-1, 3), minus(ARG1, 3)), minus(minus(ARG1, 1), minus(ARG1, ARG1)))

gp.compile(tree, pset)

def compile(expr, pset):
    """Compile the expression *expr*.

    :param expr: Expression to compile. It can either be a PrimitiveTree,
                 a string of Python code or any object that when
                 converted into string produced a valid Python code
                 expression.
    :param pset: Primitive set against which the expression is compile.
    :returns: a function if the primitive set has 1 or more arguments,
              or return the results produced by evaluating the tree.
    """
    code = str(expr)
    if len(pset.arguments) > 0:
        # This section is a stripped version of the lambdify
        # function of SymPy 0.6.6.
        args = ",".join(arg for arg in pset.arguments)
        code = "lambda {args}: {code}".format(args=args, code=code)
    try:
        return eval(code, pset.context, {})
    except MemoryError:
        _, _, traceback = sys.exc_info()
        raise MemoryError("DEAP : Error in tree evaluation :"
                            " Python cannot evaluate a tree higher than 90. "
                            "To avoid this problem, you should use bloat control on your "
                            "operators. See the DEAP documentation for more information. "
                            "DEAP will now abort.").with_traceback(traceback)

这段代码实现了一个编译函数compile,用于将表达式编译为可执行的Python代码。函数接受两个参数:expr表示要编译的表达式(一个列表),pset表示该表达式所使用的原语集合。

如果pset中定义了一个或多个参数,编译后的代码将会被包装在一个lambda函数中,并使用原语集合中定义的参数名称。否则,编译后的代码将会直接执行。

在编译完成后,函数使用eval函数将代码字符串转换为可执行的Python代码,并在pset.context命名空间中执行它。如果编译过程中出现内存错误,函数会抛出一个MemoryError异常,并显示相关错误信息。最终,函数返回一个可执行的Python函数或表达式的求值结果。

这个函数实现了将表达式编译成可执行的Python代码的功能,可以用于在遗传算法或其他优化算法中对表达式进行求解。函数接受两个参数:

  • expr:要编译的表达式,可以是一个PrimitiveTree对象、一个Python代码字符串,或者任何能够被转换为有效Python代码表达式的对象。

  • pset:表达式使用的原语集合。原语集合是一个包含基本运算符、函数、常量和变量的集合,用于构建表达式。
    如果原语集合中定义了参数,则编译的代码将会被封装在一个lambda函数中,并使用原语集合中定义的参数名称。否则,编译后的代码将会直接执行。最后,函数使用eval函数将代码字符串转换为可执行的Python代码,并在pset.context命名空间中执行它。如果编译过程中出现内存错误,函数会抛出一个MemoryError异常,并显示相关错误信息。

函数的返回值取决于原语集合中是否定义了参数。如果原语集合中定义了一个或多个参数,则函数将返回一个可执行的Python函数。否则,函数将返回表达式求值的结果。

searchSubtree

def searchSubtree(self, begin):
    """Return a slice object that corresponds to the
    range of values that defines the subtree which has the
    element with index *begin* as its root.
    """
    end = begin + 1
    total = self[begin].arity
    while total > 0:
        total += self[end].arity - 1
        end += 1
    return slice(begin, end)

Toolbox

register

def register(self, alias, function, *args, **kargs):
    """
        >>> def func(a, b, c=3):
        ...     print a, b, c
        ...
        >>> tools = Toolbox()
        >>> tools.register("myFunc", func, 2, c=4)
        >>> tools.myFunc(3)
        2 3 4
    """
    pfunc = partial(function, *args, **kargs) # 
    pfunc.__name__ = alias
    pfunc.__doc__ = function.__doc__

    if hasattr(function, "__dict__") and not isinstance(function, type):
        # Some functions don't have a dictionary, in these cases
        # simply don't copy it. Moreover, if the function is actually
        # a class, we do not want to copy the dictionary.
        pfunc.__dict__.update(function.__dict__.copy())

    setattr(self, alias, pfunc)

References

[1] 【Python】详解类的 repr() 方法
[2] python slots 详解(上篇)

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

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

相关文章

State of PostgreSQL 2023 报告解读

基于 PostgreSQL 内核的时序数据库厂商 Timescale 发布了一年一度的 State of Postgres 2023 报告。 Timescale 介绍 简单先介绍一下 Timescale 这家公司的历史。它最早是提供了一个 PG 的插件&#xff0c;引入了 Hypertable 这个概念&#xff0c;来高效地处理时序数据&…

分享一个项目——Sambert UI 声音克隆

文章目录 前言一、运行ipynb二、数据标注三、训练四、生成总结 前言 原教程视频 项目链接 运行一个ipynb&#xff0c;就可操作 总共四步 1&#xff09;运行ipynb 2&#xff09;数据标注 3&#xff09;训练 4&#xff09;生成 一、运行ipynb 等运行完毕后&#xff0c;获得该…

mt5和mt4交易软件有什么区别?

MetaTrader 4&#xff08;MT4&#xff09;和MetaTrader 5&#xff08;MT5&#xff09;是两种广泛使用的外汇和金融市场交易平台&#xff0c;由MetaQuotes公司开发。尽管它们都是外汇交易的常见选择&#xff0c;但在功能和特性上存在一些区别。以下是MT4和MT5之间的主要区别&…

2023 英特尔On技术创新大会直播 |我感受到的“芯”魅力

文章目录 每日一句正能量前言AI时代&#xff0c;云与PC结合为用户带来更好体验全新处理器&#xff0c;首次引入针对人工智能加速的NPU大模型时代&#xff0c;软硬结合带来更好训练成果后记 每日一句正能量 成长是一条必走的路路上我们伤痛在所难免。 前言 在2023年的英特尔On技…

Go语言HTTP编程入门指南

如果你是一名开发者&#xff0c;那么你一定听说过Go语言。Go&#xff0c;也被称为Golang&#xff0c;是由Google开发的一种静态类型、编译型语言。它的设计理念是“简单、快速、高效”&#xff0c;这使得Go语言在许多方面都表现出色&#xff0c;尤其是在网络编程和并发编程方面…

fastGitHub工具推荐(如果打不开github或者使用很慢可以使用该工具)

目录 一&#xff0c;针对问题二&#xff0c;下载1&#xff0c;github里面下载FastGitHub2&#xff0c;博客上传了下载资源 三&#xff0c;安装使用点击执行文件即可 一&#xff0c;针对问题 当使用github很慢&#xff0c;或者根本打不开的时候&#xff0c;就可以使用该工具 …

HDFS NFS Gateway(环境配置,超级详细!!)

HDFS NFS Gateway简介: ​ HDFS NFS Gateway是Hadoop Distributed File System&#xff08;HDFS&#xff09;中的一个组件&#xff0c;它允许客户端通过NFS&#xff08;Network File System&#xff0c;网络文件系统&#xff09;与HDFS进行交互。具体来说&#xff0c;HDFS NFS…

搭建esp32-idf开发环境并烧入第一个程序

ESP32下载idf并烧入第一个程序 一.官网下载idf安装包二.安装idf三 .测试安装是否成功3.1进入idf控制台3.2 查看安装版本3.3 编译工程 四.下载程序4.1查看所在端口4.2下载程序4.3 监听串口 一.官网下载idf安装包 点击下载 如图&#xff1a; 我们选择离线下载&#xff0c;注意…

行业前景咋样?大厂找我用C++抓取化工产品数据并分析

最近又来活了&#xff0c;天天忙到半夜&#xff0c;但是想想收益还是再坚持坚持。是这么一回事&#xff0c;兄弟所在的化工公司最近想看看某些行业数据&#xff0c;看看市面的同类型产品销量收益等情况是否满足预期效果&#xff0c;也就找到我让我给用爬虫写一个采集并分析的报…

如何实现设备联网控制?

在工业自动化领域&#xff0c;设备联网控制已经成为一种趋势。通过设备联网&#xff0c;可以实现设备的远程监控和管理&#xff0c;提高设备的可用性和效率。本文将介绍如何实现设备联网控制。 设备如何联网&#xff1f; 使用网关联网&#xff1a; HiWoo Box是一款功能强大的…

Sectigo的ov多域名ssl证书

OV多域名SSL证书和EV多域名SSL证书都只支持企事业单位申请&#xff0c;但是EV多域名SSL证书审核比较严格&#xff0c;价格也比较高&#xff0c;OV多域名SSL证书能加密网站传输数据&#xff0c;也能对服务器身份进行认证。对于大多数事业单位&#xff0c;OV多域名SSL证书就能满足…

外贸业务员该如何写好一份有质感的年终总结?内附外贸大神例文

庄子云&#xff1a;人生天地之间&#xff0c;若白驹之过隙&#xff0c;忽然而已... 2023年注定是不平凡的一年&#xff0c;临近年终&#xff0c;你可能听到最多的关键词就是外贸有点难做。不管是因为什么&#xff0c;客观来说2023年的外贸之路确实不太平坦&#xff0c;最近胡塞…

车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着社会的不断发展和交通工具的普及&#xff0c;车辆违规行为成为了一个严重的问题。其中&#xff0c;车辆违规开启远光灯是一种常见的违规行为&#xff0c;给其…

快速能访问服务器的文件

1、背景 访问ubuntu上的文件 2、方法 python3 -m http.server 8081 --directory /home/ NAS 共享访问协议 — NFS、SMB、FTP、WebDAV 各有何优势&#xff1f;http://1 Ubuntu 搭建文件服务器&#xff08;Nginx&#xff09;

【开源】USB转4路RS422+4路RS485电路板设计

简介 CH348Q是沁恒出品的一款USB转8路串口的芯片&#xff0c;USB为2.0接口&#xff0c;其中4路串口支持流控&#xff0c;另外4路不支持流控&#xff0c;之前介绍过一款开源USB转8路串口的板子&#xff0c;文章链接&#xff1a;https://mp.weixin.qq.com/s/KsrV3nwemQyq3tdv7Lk…

超分辨数据集:Set5 Set14 BSD100 Urban100 Manga109

DIV2K数据集官网上很好找到&#xff0c;但是网上流传的Set5 14 BSD100,Urban100 Manga109都是私人进行处理过的版本&#xff0c;各个处理方式都不同&#xff0c;为了统一方式写了这篇文章。 官方的DIV2K x2、x3、x4的LR图片使用下面matlab代码生成&#xff08;已经经过测试最后…

精细经营:为 Web3 游戏长期卓越奠定基石

作者&#xff1a;lesleyfootprint.network 随着越来越多的人涌入 Web3 游戏世界&#xff0c;构建精细化运营体系成为保持项目长期发展的关键。充分利用数据分析对于明智的决策至关重要&#xff0c;它能揭示用户行为、交易模式和市场趋势的内在奥秘。 基于数据驱动的决策、风险…

汤晓鸥:以科技改变世界,以教育照亮未来

原创 | 文 BFT机器人 汤晓鸥是我国人工智能领域的杰出代表&#xff0c;也是商汤科技的创始人。他在AI领域有着深厚的研究背景和丰富的实践经验&#xff0c;其主要研究方向是计算机视觉&#xff08;CV&#xff09;、模式识别和视频处理。 汤晓鸥积极推动AI技术的发展&#xff0…

uniapp实现豆瓣电影微信小程序(附源码)

演示 运行 基于本地代理1 npm run dev:proxy1基于本地代理2 npm run dev:proxy2基于nginx 代理 npm run dev:nginx目录结构 |__ douban # 本地代理|__ app.js # 方式 1|__ proxy.js …

深度学习的十大核心算法

引言 深度学习是人工智能领域中最热门和最具影响力的分支之一。其核心在于通过构建复杂的神经网络模型&#xff0c;从大量的数据中自动学习并提取出有用的特征&#xff0c;从而实现各种高级的任务&#xff0c;如图像识别、自然语言处理等。本文将介绍深度学习中的十大核心算法…