4.点云数据的配准

1.点云配准ICP(Iterative Closest Point)算法

点云配准的原理及ICP(Iterative Closest Point)算法原理参照博客【PCL】—— 点云配准ICP(Iterative Closest Point)算法_icp点云配准-CSDN博客。

(1)点云配准原理:三维扫描仪设备对目标物体一次扫描往往只能获取到局部的点云信息(如物体背面无法一次扫描到),因此需要进行多次扫描,而每次扫描时得到的点云都有独立的坐标系,不可以直接进行拼接。因此要得到目标物体的完整点云就需要对多个局部点云进行配准。为了得到被测物体的完整数据模型,需要确定一个合适的坐标变换 ,将从各个视角得到的点集合并到一个统一的坐标系下形成一个完整的数据点云,然后就可以方便地进行可视化等操作,这就是点云数据的配准。

        点云配准步骤上可以分为粗配准(Coarse Registration)和精配准(Fine Registration)两个阶段。

        粗配准是指在点云相对位姿完全未知的情况下对点云进行配准,找到一个可以让两块点云相对近似的旋转平移变换矩阵,进而将待配准点云数据转换到统一的坐标系内,可以为精配准提供良好的初始值。

​     精配准是指在粗配准的基础上,让点云之间的空间位置差异最小化,得到一个更加精准的旋转平移变换矩阵。该算法的运行速度以及向全局最优化的收敛性却在很大程度上依赖于给定的初始变换估计以及在迭代过程中对应关系的确立。所以需要各种粗配准技术为ICP算法提供较好的位置,在迭代过程中确立正确对应点集能避免迭代陷入局部极值,决定了算法的收敛速度和最终的配准精度。

​     比较常见的一种配准算法是迭代最近点算法(Iterative Closest Point, ICP)。ICP算法可以基于四元数求解,也可以基于奇异值分解(SVD)求解,本文主要介绍基于奇异值分解的ICP算法。

(2)ICP原理

 的

        给定一个参考点集P和一个数据点集Q(在给定的初始估计R,t),算法为Q中的每个点寻找P中对应的最近点,形成匹配点对。然后,将所有匹配点对的欧氏距离之和作为待求解的目标函数,利用奇异值分解求出R和t以使目标函数最小,根据R, t 转换得到新的'Q ′并再次找到对应的点对,如此迭代。

缺点:需要剔除噪声点(距离过大的点对或包含边界点的点对)。基于点对的配准不包括局部形状信息。在每次迭代中搜索最近点非常耗时。计算可能陷入局部最优。

​     一般来说,ICP可以分为以下四个阶段

  1. 对原始点云数据进行采样
  2. 确定初始对应点集
  3. 去除错误对应点集
  4. 坐标变换的求解

数学原理

问题定义

案例实现

官方教程——How to use iterative closest point — Point Cloud Library 0.0 documentation

(3)ICP配准代码如下:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>

int
mains() {
    // 定义输入和输出点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);

    // 随机填充无序点云
    cloud_in->width = 5;
    cloud_in->height = 1;
    cloud_in->is_dense = false;
    cloud_in->points.resize(cloud_in->width * cloud_in->height);
    for (size_t i = 0; i < cloud_in->points.size(); ++i) {
        cloud_in->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud_in->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud_in->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }
    std::cout << "Saved " << cloud_in->points.size() << " data points to input:"
        << std::endl;
    for (size_t i = 0; i < cloud_in->points.size(); ++i)
        std::cout << "    " <<
        cloud_in->points[i].x << " " << cloud_in->points[i].y << " " <<
        cloud_in->points[i].z << std::endl;
    *cloud_out = *cloud_in;
    std::cout << "size:" << cloud_out->points.size() << std::endl;

    // 在点云上执行简单的刚性变换,将cloud_out中的x平移0.7f米,然后再次输出数据值。
    for (size_t i = 0; i < cloud_in->points.size(); ++i)
        cloud_out->points[i].x = cloud_in->points[i].x + 0.7f;
    // 打印这些点
    std::cout << "Transformed " << cloud_in->points.size() << " data points:"
        << std::endl;
    for (size_t i = 0; i < cloud_out->points.size(); ++i)
        std::cout << "    " << cloud_out->points[i].x << " " <<
        cloud_out->points[i].y << " " << cloud_out->points[i].z << std::endl;

    // 创建IterativeClosestPoint的实例
    // setInputSource将cloud_in作为输入点云
    // setInputTarget将平移后的cloud_out作为目标点云
    pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
    icp.setInputSource(cloud_in);
    icp.setInputTarget(cloud_out);

    // 创建一个 pcl::PointCloud<pcl::PointXYZ>实例 Final 对象,存储配准变换后的源点云,
    // 应用 ICP 算法后, IterativeClosestPoint 能够保存结果点云集,如果这两个点云匹配正确的话
    // (即仅对其中一个应用某种刚体变换,就可以得到两个在同一坐标系下相同的点云),那么 icp. hasConverged()= 1 (true),
    // 然后会输出最终变换矩阵的匹配分数和变换矩阵等信息。
    pcl::PointCloud<pcl::PointXYZ> Final;
    icp.align(Final);
    std::cout << "has converged:" << icp.hasConverged() << " score: " <<
        icp.getFitnessScore() << std::endl;
    const pcl::Registration<pcl::PointXYZ, pcl::PointXYZ, float>::Matrix4& matrix = icp.getFinalTransformation();
    std::cout << matrix << std::endl;
    return (0);
}

自己的想法:点云配准是为了获取坐标转换的一个4维矩阵(旋转矩阵加平移向量),配准所有点云数据增加了计算量,因此可以先去噪,再分割出目标,再找目标的关键点,对关键点进行配准。

交互式ICP配准
官方教程——https://pcl.readthedocs.io/projects/tutorials/en/latest/interactive_icp.html

该程序将加载点云并对其施加刚性变换。 之后,ICP算法会将变换后的点云与原始对齐。 每次用户按下“空格”,都会进行一次ICP迭代,并刷新查看器。

代码如下:

#include <string>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>   // TicToc
 
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

bool next_iteration = false;

void
print4x4Matrix (const Eigen::Matrix4d & matrix)
{
    printf ("Rotation matrix :\n");
    printf ("    | %6.3f %6.3f %6.3f | \n", matrix (0, 0), matrix (0, 1), matrix (0, 2));
    printf ("R = | %6.3f %6.3f %6.3f | \n", matrix (1, 0), matrix (1, 1), matrix (1, 2));
    printf ("    | %6.3f %6.3f %6.3f | \n", matrix (2, 0), matrix (2, 1), matrix (2, 2));
    printf ("Translation vector :\n");
    printf ("t = < %6.3f, %6.3f, %6.3f >\n\n", matrix (0, 3), matrix (1, 3), matrix (2, 3));
}
/**
 * 此函数是查看器的回调。 当查看器窗口位于顶部时,只要按任意键,就会调用此函数。 如果碰到“空格”; 将布尔值设置为true。
 * @param event
 * @param nothing
 */
void
keyboardEventOccurred (const pcl::visualization::KeyboardEvent& event,
                       void* nothing)
{
    if (event.getKeySym () == "space" && event.keyDown ())
        next_iteration = true;
}

int
main (int argc,
      char* argv[])
{
    // The point clouds we will be using
    PointCloudT::Ptr cloud_in (new PointCloudT);  // Original point cloud
    PointCloudT::Ptr cloud_tr (new PointCloudT);  // Transformed point cloud
    PointCloudT::Ptr cloud_icp (new PointCloudT);  // ICP output point cloud

//    我们检查程序的参数,设置初始ICP迭代的次数,然后尝试加载PCD文件。
    // Checking program arguments
    if (argc < 2)
    {
        printf ("Usage :\n");
        printf ("\t\t%s file.pcd number_of_ICP_iterations\n", argv[0]);
        PCL_ERROR ("Provide one pcd file.\n");
        return (-1);
    }

    int iterations = 1;  // Default number of ICP iterations
    if (argc > 2)
    {
        // If the user passed the number of iteration as an argument
        iterations = atoi (argv[2]);
        if (iterations < 1)
        {
            PCL_ERROR ("Number of initial iterations must be >= 1\n");
            return (-1);
        }
    }

    pcl::console::TicToc time;
    time.tic ();
    if (pcl::io::loadPCDFile (argv[1], *cloud_in) < 0)
    {
        PCL_ERROR ("Error loading cloud %s.\n", argv[1]);
        return (-1);
    }
    std::cout << "\nLoaded file " << argv[1] << " (" << cloud_in->size () << " points) in " << time.toc () << " ms\n" << std::endl;

    // 我们使用刚性矩阵变换来变换原始点云。
    // cloud_in包含原始点云。
    // cloud_tr和cloud_icp包含平移/旋转的点云。
    // cloud_tr是我们将用于显示的备份(绿点云)。

    // Defining a rotation matrix and translation vector
    Eigen::Matrix4d transformation_matrix = Eigen::Matrix4d::Identity ();

    // A rotation matrix (see https://en.wikipedia.org/wiki/Rotation_matrix)
    double theta = M_PI / 8;  // The angle of rotation in radians
    transformation_matrix (0, 0) = std::cos (theta);
    transformation_matrix (0, 1) = -sin (theta);
    transformation_matrix (1, 0) = sin (theta);
    transformation_matrix (1, 1) = std::cos (theta);

    // A translation on Z axis (0.4 meters)
    transformation_matrix (2, 3) = 0.4;

    // Display in terminal the transformation matrix
    std::cout << "Applying this rigid transformation to: cloud_in -> cloud_icp" << std::endl;
    print4x4Matrix (transformation_matrix);

    // Executing the transformation
    pcl::transformPointCloud (*cloud_in, *cloud_icp, transformation_matrix);
    *cloud_tr = *cloud_icp;  // We backup cloud_icp into cloud_tr for later use

    // 这是ICP对象的创建。 我们设置ICP算法的参数。
    // setMaximumIterations(iterations)设置要执行的初始迭代次数(默认值为1)。
    // 然后,我们将点云转换为cloud_icp。 第一次对齐后,我们将在下一次使用该ICP对象时(当用户按下“空格”时)将ICP最大迭代次数设置为1。

    // The Iterative Closest Point algorithm
    time.tic ();
    pcl::IterativeClosestPoint<PointT, PointT> icp;
    icp.setMaximumIterations (iterations);
    icp.setInputSource (cloud_icp);
    icp.setInputTarget (cloud_in);
    icp.align (*cloud_icp);
    icp.setMaximumIterations (1);  // We set this variable to 1 for the next time we will call .align () function
    std::cout << "Applied " << iterations << " ICP iteration(s) in " << time.toc () << " ms" << std::endl;

    // 检查ICP算法是否收敛; 否则退出程序。 如果返回true,我们将转换矩阵存储在4x4矩阵中,然后打印刚性矩阵转换。
    if (icp.hasConverged ())
    {
        std::cout << "\nICP has converged, score is " << icp.getFitnessScore () << std::endl;
        std::cout << "\nICP transformation " << iterations << " : cloud_icp -> cloud_in" << std::endl;
        transformation_matrix = icp.getFinalTransformation ().cast<double>();
        print4x4Matrix (transformation_matrix);
    }
    else
    {
        PCL_ERROR ("\nICP has not converged.\n");
        return (-1);
    }

    // Visualization
    pcl::visualization::PCLVisualizer viewer ("ICP demo");
    // Create two vertically separated viewports
    int v1 (0);
    int v2 (1);
    viewer.createViewPort (0.0, 0.0, 0.5, 1.0, v1);
    viewer.createViewPort (0.5, 0.0, 1.0, 1.0, v2);

    // The color we will be using
    float bckgr_gray_level = 0.0;  // Black
    float txt_gray_lvl = 1.0 - bckgr_gray_level;

    // Original point cloud is white
    pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_in_color_h (cloud_in, (int) 255 * txt_gray_lvl, (int) 255 * txt_gray_lvl,
                                                                               (int) 255 * txt_gray_lvl);
    viewer.addPointCloud (cloud_in, cloud_in_color_h, "cloud_in_v1", v1);
    viewer.addPointCloud (cloud_in, cloud_in_color_h, "cloud_in_v2", v2);

    // Transformed point cloud is green
    pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_tr_color_h (cloud_tr, 20, 180, 20);
    viewer.addPointCloud (cloud_tr, cloud_tr_color_h, "cloud_tr_v1", v1);

    // ICP aligned point cloud is red
    pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_icp_color_h (cloud_icp, 180, 20, 20);
    viewer.addPointCloud (cloud_icp, cloud_icp_color_h, "cloud_icp_v2", v2);

    // Adding text descriptions in each viewport
    viewer.addText ("White: Original point cloud\nGreen: Matrix transformed point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_1", v1);
    viewer.addText ("White: Original point cloud\nRed: ICP aligned point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_2", v2);

    std::stringstream ss;
    ss << iterations;
    std::string iterations_cnt = "ICP iterations = " + ss.str ();
    viewer.addText (iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt", v2);

    // Set background color
    viewer.setBackgroundColor (bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v1);
    viewer.setBackgroundColor (bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v2);

    // Set camera position and orientation
    viewer.setCameraPosition (-3.68332, 2.94092, 5.71266, 0.289847, 0.921947, -0.256907, 0);
    viewer.setSize (1280, 1024);  // Visualiser window size

    // Register keyboard callback :
    viewer.registerKeyboardCallback (&keyboardEventOccurred, (void*) NULL);

    // Display the visualiser
    while (!viewer.wasStopped ())
    {
        viewer.spinOnce ();

        // The user pressed "space" :
        if (next_iteration)
        {
            // The Iterative Closest Point algorithm
            time.tic ();
            // 如果用户按下键盘上的任意键,则会调用keyboardEventOccurred函数。 此功能检查键是否为“空格”。
            // 如果是,则全局布尔值next_iteration设置为true,从而允许查看器循环输入代码的下一部分:调用ICP对象以进行对齐。
            // 记住,我们已经配置了该对象输入/输出云,并且之前通过setMaximumIterations将最大迭代次数设置为1。

            icp.align (*cloud_icp);
            std::cout << "Applied 1 ICP iteration in " << time.toc () << " ms" << std::endl;

            // 和以前一样,我们检查ICP是否收敛,如果不收敛,则退出程序。
            if (icp.hasConverged ())
            {
                // printf(“ 033 [11A”); 在终端增加11行以覆盖显示的最后一个矩阵是一个小技巧。
                // 简而言之,它允许替换文本而不是编写新行; 使输出更具可读性。 我们增加迭代次数以更新可视化器中的文本值。
                printf ("\033[11A");  // Go up 11 lines in terminal output.
                printf ("\nICP has converged, score is %+.0e\n", icp.getFitnessScore ());

                // 这意味着,如果您已经完成了10次迭代,则此函数返回矩阵以将点云从迭代10转换为11。
                std::cout << "\nICP transformation " << ++iterations << " : cloud_icp -> cloud_in" << std::endl;

                // 函数getFinalTransformation()返回在迭代过程中完成的刚性矩阵转换(此处为1次迭代)。
                transformation_matrix *= icp.getFinalTransformation ().cast<double>();  // WARNING /!\ This is not accurate! For "educational" purpose only!
                print4x4Matrix (transformation_matrix);  // Print the transformation between original pose and current pose

                ss.str ("");
                ss << iterations;
                std::string iterations_cnt = "ICP iterations = " + ss.str ();
                viewer.updateText (iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt");
                viewer.updatePointCloud (cloud_icp, cloud_icp_color_h, "cloud_icp_v2");
            }
            else
            {
                PCL_ERROR ("\nICP has not converged.\n");
                return (-1);
            }

            //这不是我们想要的。 如果我们将最后一个矩阵与新矩阵相乘,那么结果就是从开始到当前迭代的转换矩阵。
        }
        next_iteration = false;
    }
    return (0);
}

2.

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

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

相关文章

Spring Cloud Gateway详细介绍以及实现动态路由

一. 简介 Spring Cloud Gateway This project provides a libraries for building an API Gateway on top of Spring WebFlux or Spring WebMVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to …

Mysql学习大纲

文章目录 整体大纲总结 整体大纲 大纲 MySQL在金融互联网行业的企业级安装部署mysql启动关闭原理和实战&#xff0c;及常见错误排查 花钱9.9 订阅了专栏MySQL字符集和校对规则史上最详细的Mysql用户权原理和实战&#xff0c;生产案例InnoDB引擎原理和实战&#xff0c;通俗易懂…

[C++][算法基础]求组合数(II)

给定 &#x1d45b; 组询问&#xff0c;每组询问给定两个整数 &#x1d44e;&#xff0c;&#x1d44f;&#xff0c;请你输出 的值。 输入格式 第一行包含整数 &#x1d45b;。 接下来 &#x1d45b; 行&#xff0c;每行包含一组 &#x1d44e; 和 &#x1d44f;。 输出格…

vue3左树的全选和反选

<el-input v-model"filterText" placeholder"" style"width: 48%"/><el-button type"primary" click"handleSearch" class"ml-2">查找</el-button><el-radio-group v-model"form.choic…

一文扫盲(5):实验室管理系统的界面设计

本次带来第5期&#xff1a;实验室管理系统的设计&#xff0c;从系统定义、功能模块、界面构成和设计着力点四个方面讲解&#xff0c;大千UI工场愿意持续和大家分享&#xff0c;欢迎关注、点赞、转发。 一、什么是实验室管理系统 实验室管理系统是一种用于管理和监控实验室运作…

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

目录 一、前言 二、友元是什么&#xff1f; 三、友元的感性理解和分类 &#x1f95d;友元的感性理解 &#x1f34b;友元的三种分类 ✨友元 --- 全局函数 ✨友元 --- 成员函数 ✨友元 --- 类 四、友元函数的应用场景 &#x1f34d;操作符重载 :"<<" 与…

Nacos的介绍和使用Docker、MySQL持久化挂载安装

文章目录 Nacos的介绍和使用Docker、MySQL持久化挂载安装一、Nacos的介绍二、使用Docker和MySQL进行持久化安装1、选择想要使用的MySQL服务器&#xff0c;创建一个数据库nacos-config&#xff0c;然后运行下面sql2、在linux下的opt文件夹下创建 /opt/nacos/data文件夹 和 /opt/…

“卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法

原文链接&#xff1a;“卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601940&idx6&sn515e01666037570939aaf0eee56f46d1&chksmfa820ef3cdf587e5276eac181c890026b6ca4bc36ce0e4f80d89d…

测试的分类(2)

目录 按照执行方式分类 静态测试 动态测试 按照测试方法 灰盒测试 按照测试阶段分类 单元测试 集成测试 系统测试 冒烟测试 回归测试 按照执行方式分类 静态测试 所谓静态测试就是不实际运行被测软件,只是静态地检查程序代码, 界面或文档中可能存在错误的过程. 不以…

优先级队列(概念理解/底层模拟/时间复杂度分析)

目录 1.概念理解 2.优先级队列的底层模拟 2.1堆的概念 2.2优先队列的模拟实现 2.2.1把Heap类定义好 2.2.2初始化堆 2.2.3创建大堆 1.思路 以此二叉树为例&#xff1a; 图文理解&#xff1a; 2.思路转化为代码 2.2.4堆操作之offer&#xff08;进队列&#xff09; 1…

初识java——jdk?环境变量?及关于安装jdk的步骤

文章目录 JDK的安装在安装JDK时遇到的问题&#xff1a; 背景知识一 什么是jdkjdk简介jdk文件详解&#xff1a;1 bin目录&#xff1a;2 lib目录&#xff1a;3 include目录.exe文件是可执行的应用程序&#xff0c;这个我们都清楚&#xff0c;但.dll文件又是做什么的呢&#xff1f…

Advanced RAG 04:重排序(Re-ranking)技术探讨

编者按&#xff1a;重排序&#xff08;Re-ranking&#xff09;技术在检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;系统中扮演着关键角色。通过对检索到的上下文进行筛选和排序&#xff0c;可以提高 RAG 系统的有效性和准确性&#xff0…

查找算法之顺序查找

目录 前言一、查找算法预备知识二、顺序查找三、总结3.1 查找性能3.2 适用场景 前言 查找算法是一种用于在数据集合中查找特定元素的算法。在计算机科学中&#xff0c;查找算法通常被用于在数组、链表、树等数据结构中查找目标元素的位置或者判断目标元素是否存在。 查找算法的…

爱尔兰启动其首个量子技术国家战略“量子 2030”

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨王珩 排版丨沛贤 800字丨5分钟阅读 摘要&#xff1a;爱尔兰推出了“量子 2030”&#xff0c;这是爱尔兰第一个量子技术国家战略。“量子 2030”将爱尔兰量子技术界的努力重点放在爱尔兰可以…

电脑文件加密软件有哪些?文件加密软件哪个好?

某企业的一位员工因不慎将包含敏感客户数据的电脑丢失&#xff0c;导致企业面临巨大的法律风险和经济损失。 这一事件凸显了电脑文件加密的必要性。 如果该企业事先采用了文件加密软件对敏感数据进行保护&#xff0c;即使电脑丢失&#xff0c;攻击者也无法轻易获取到文件内容…

STL_List与萃取

List 参考文章: https://blog.csdn.net/weixin_45389639/article/details/121618243 List源码 List中节点的定义&#xff1a; list是双向列表&#xff0c;所以其中节点需要包含指向前一节点和后一节点的指针&#xff0c; data是节点中存储的数据类型 template <class _Tp&g…

HCIP——MPLS(笔记)

MPLS--多协议标签交换技术 包交换 数据组成数据包&#xff0c;之后&#xff0c;在各个网络节点中不断传递&#xff0c;最终到达目标。包交换转发效率不高的问题所在&#xff1a;1&#xff0c;在整个包交换的过程中&#xff0c;需要先查询路由表之后再查看ARP缓存表两张表来完…

Java:内部类

目录 1.内部类介绍2.实例内部类3.静态内部类4.局部内部类5.匿名内部类 1.内部类介绍 当一个事物的内部&#xff0c;还有一个部分需要一个完整的结构进行描述&#xff0c;而这个内部的完整的结构又只为外部事物提供服务&#xff0c;那么这个内部的完整结构最好使用内部类。在 J…

KDD‘23 | AlphaMix: 高效专家混合框架(MoE)显著提高上证50选股表现

KDD23 | AlphaMix: 高效专家混合框架&#xff08;MoE&#xff09;显著提高上证50选股表现 原创 QuantML QuantML 2024-04-18 09:17 上海 Content 本文提出了一个名为AlphaMix的新型三阶段专家混合&#xff08;Mixture-of-Experts&#xff0c;MoE&#xff09;框架&#xff0c;…

信息流广告大行其是,微博回望“原生”的初心

摘要&#xff1a;有流量的地方&#xff0c;就当有原生信息流广告 信息流广告&#xff0c;自2006年Facebook推出后就迅速火遍全球数字营销界&#xff0c;被誉为实现了广告主、用户、媒体平台三赢。特别是随着OCPM/OCPX大放异彩&#xff0c;信息流广告几乎成为广告主的必选项&…