周三下午,机器人调试间。

"你看这条弧焊轨迹,"调试员小赵把激光跟踪仪的报告甩在桌上,"新到的弧焊机器人,标称重复定位精度 ±0.05mm,但跑了一圈 2 米长焊缝,末端实际轨迹跟编程轨迹差了 0.42mm。而且不是固定的——跑 0.5 米差 0.12mm,跑 1 米差 0.25mm,跑 2 米差 0.42mm,跑 3 米直接到 0.68mm。距离越长误差越大,但没人说得清到底什么关系。"

我点开他导出的 CSV。

"这表里有什么?"我问。

"每次标定采集的数据:运行距离(m)、各关节角度、末端实际位置(XYZ)、理论位置(XYZ)、定位误差(mm)、速度(mm/s)、负载(kg)、环境温度(℃),"小赵说,"但它就是一张误差记录表。你能看到误差随距离在涨,但工艺卡上写的是'定位精度 ±0.1mm'——那是空载短距离的指标。实际焊接 2 米长焊缝,我怎么预判误差会到多少?总不能每换一种焊缝长度就重新拿激光跟踪仪测一遍吧?"

"我就想干一件事,"小赵说,"给我一个程序:把历史轨迹误差数据灌进去,建个回归模型,输入'我要跑多长的距离',直接输出'预估定位误差是多少'。我拿去跟工艺员说'这条 2.5 米焊缝,预计末端误差 0.52mm,超了工艺要求的 0.3mm,得加中间标点或者分段焊'。"

"比如误差跟运行距离不是简单的线性关系——可能是距离的一次项+二次项叠加,因为连杆柔性变形和齿轮间隙都随行程累积,"我接话,"用 pandas 做数据清洗+特征工程,numpy 算误差统计量,scikit-learn 的 PolynomialFeatures 做距离多项式展开,用 Ridge 回归拟合'距离→误差'的映射,再跟 Linear/Pipeline 对比。scipy 做残差正态性检验和置信区间,matplotlib 画实际距离vs误差散点+回归拟合曲线+残差分布+特征重要性+多项式阶数对比+预测误差带,networkx 建'特征→模型→预测'的推理链路。"

"对,"小赵点头,"别给我黑盒,要能说清楚'为什么跑 2 米误差是 0.42 而不是 0.2'。我看得懂,能拿去跟质量部门解释'误差 = 0.05 + 0.08×距离 + 0.03×距离²,R²=0.96,距离是最主要因素'。"

"用 pandas 做特征工程,sklearn Ridge 回归+多项式,scipy 残差检验,matplotlib 出 6 图+报告,存 results/,"我开工程,"数据自包含,合成一批 80 条轨迹误差记录(距离 0.2-5m),下载就能跑。"

敲了行原型:

# 误差模型: error = β₀ + β₁×distance + β₂×distance² + β₃×speed + β₄×payload + ε

# Ridge 回归 → 防止过拟合(多项式高阶容易炸)

# 输入: 运行距离 → 输出: 预测误差 + 95%置信区间

# 残差检验 → 模型靠不靠谱

 

"完整版 OOP 封好,"我说,"数据加载器、特征工程器、回归建模器、模型评估器、可视化器、推理链路,输出误差预测+6图+报告。"

小赵凑近看:"那以后看报告:Ridge 回归 R²=0.967,距离解释了 78% 的误差变异,速度 12%,负载 7%。预测 2.5 米焊缝的误差 0.52±0.06mm(95% CI)。多项式 2 阶最优,3 阶开始过拟合。残差基本正态,模型可信。结论:超过 1.8 米的长焊缝必须分段或加中间标点,单段精度保不住。"

"对,"我接话,"机器人不是标称 ±0.05mm 就永远 ±0.05mm,是'跑得越远飘得越多'。数字孪生里挂误差预测节点,这套就是编程员的'长轨迹精度预警器'。"

 

一、实际应用场景(真实痛点)

 

场景设定:工业机器人在执行长轨迹任务(弧焊、涂胶、切割)时,末端定位误差随运行距离增加而累积。工艺部门按"标称重复定位精度"制定工艺卡,但实际长轨迹误差远超标称值,导致焊接偏缝、涂胶断线、切割过切等质量问题。

 

现场原话(叙事化):

 

"不是机器人精度不行,"小赵说,"是标称精度是空载短距离测的。实际干 2.5 米长焊缝,连杆柔性变形、齿轮反向间隙、温度漂移全叠加起来,末端能飘到 0.5mm 以上。但工艺卡上写的是'定位精度 ±0.1mm'——那是跑 0.3 米短轨迹的指标。我拿这个指标去编 2.5 米的程序,焊出来整条缝偏移,质检不过关。"

"最坑的是没有预判手段,"小赵补充,"每次换新产品,焊缝长度变了,我就得重新拿激光跟踪仪测一遍实际误差。一个产品测 3 天,测完发现超差,改方案,再测。如果有个模型能根据历史数据告诉我'跑 2 米大概飘多少',我就能提前决定要不要分段焊或者加中间标点。现在全靠猜。"

核心矛盾:"标称精度指标 + 经验猜测" 与 "数据驱动的误差回归模型 + 距离-误差量化映射 + 长轨迹精度预警" 之间的断层。

 

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

 

《先进制造技术》模块 本篇痛点对应

工业机器人技术基础:机器人运动学与精度分析 定位误差建模与预测

先进制造技术基础:几何量公差与测量 误差累积规律量化

智能制造与数字孪生:过程建模与预测 数据驱动的误差预测

数控加工与CAD/CAM技术:轨迹规划精度 长轨迹分段策略

 

一句话总结:我们需要一个"机器人轨迹误差数据→特征工程+多项式Ridge回归+残差检验+误差带预测程序",用 

"pandas" 做数据清洗/特征构造,

"numpy" 做统计量计算,

"scikit-learn" 多项式回归+模型对比,

"scipy" 残差正态性检验+置信区间,

"matplotlib" 画散点+回归曲线+残差分布+特征重要性+阶数对比+预测误差带,

"networkx" 建推理链路,实现从"标称精度查手册"到"数据驱动的误差量化预测+长轨迹精度预警"。

 

三、核心逻辑讲解(大白话)

 

3.1 问题本质:把机器人想成"尺子"

 

把机器人末端定位想成用一把会弯的尺子画线:

 

* 运行距离 = 你画的线有多长

* 定位误差 = 尺子弯了多少(线画歪了多少)

* 核心发现 = 线越长,尺子弯得越多——但不是直线变弯,是加速变弯(二次关系)

* 为什么 = 连杆柔性(距离越长关节转得越多→柔性变形越大)+ 齿轮间隙累积 + 温度漂移

* 你的目标 = 给一个距离,直接告诉你"大概会偏多少"

 

3.2 业务逻辑 → 代码映射

 

导入机器人轨迹误差数据

   │

   ▼ TrajectoryDataLoader (pandas)

读取表:

  运行距离(m), 各关节角度(°), 末端实际XYZ(mm),

  理论XYZ(mm), 定位误差(mm), 速度(mm/s),

  负载(kg), 环境温度(℃)

   │

   ▼ FeatureEngineer (pandas + numpy)

特征工程:

  距离 → 多项式展开(distance, distance², distance³)

  速度分组 → 低速/中速/高速

  负载分组 → 轻载/中载/重载

  误差计算 → 欧氏距离(实际-理论)

   │

   ▼ RegressionModeler (scikit-learn)

回归建模:

  Ridge 回归(多项式2阶) → 防过拟合

  Linear 回归 → 基线对比

  Pipeline(StandardScaler + Ridge) → 标准化

  交叉验证 → 选最佳 alpha

   │

   ▼ ModelEvaluator (scipy + sklearn)

模型评估:

  R², MSE, MAE

  残差正态性 → Shapiro-Wilk

  残差自相关 → Durbin-Watson

  95% 置信区间 → prediction interval

   │

   ▼ TrajectoryVisualizer (matplotlib + networkx)

可视化:

  1. 距离-误差散点+回归曲线

  2. 残差分布直方图+Q-Q

  3. 特征系数条形图

  4. 多项式阶数对比(R² vs degree)

  5. 预测误差带(均值±2σ)

  6. 推理链路网络图

   │

   ▼ SyntheticTrajectoryData (numpy)

合成数据:

  80条轨迹 × 距离0.2-5m

  误差 = 0.05 + 0.08×d + 0.03×d² + 噪声

  可复现

 

3.3 为什么不能"看标称精度"

 

视角 问题

标称 ±0.05mm 空载短距离,实际长轨迹完全不适用

经验法则 "长焊缝多留余量"——留多少?不知道

回归模型 输入距离→输出误差+置信区间

多项式 捕捉加速累积效应

残差检验 验证模型靠不靠谱

 

3.4 分析前后对比

 

维度 传统方式 本程序

误差预估 查手册/凭经验 回归模型量化预测

长轨迹策略 一刀切分段 按预测误差阈值分段

模型可信度 不知道 残差检验+交叉验证

输出 "差不多吧" 0.52±0.06mm (95% CI)

 

四、OOP 代码实现

 

4.1 项目结构

 

robot_error_predictor/

├── robot_error_predictor/

│ ├── __init__.py

│ ├── trajectory_data_loader.py # 数据加载

│ ├── feature_engineer.py # 特征工程

│ ├── regression_modeler.py # 回归建模

│ ├── model_evaluator.py # 模型评估

│ ├── trajectory_visualizer.py # 可视化

│ └── synthetic_trajectory_data.py # 合成数据

├── tests/

│ ├── __init__.py

│ └── test_trajectory.py

├── results/

│ ├── scatter_regression.png

│ ├── residual_analysis.png

│ ├── feature_coefficients.png

│ ├── degree_comparison.png

│ ├── prediction_band.png

│ ├── inference_network.png

│ ├── prediction_detail.csv

│ └── error_report.txt

└── run_trajectory.py

 

4.2 核心源码

 

<details>

 

<summary></summary>

 

"""机器人轨迹误差数据加载器"""

 

import pandas as pd

from pathlib import Path

from typing import Optional

 

 

class TrajectoryDataLoader:

    """读取机器人轨迹误差数据集"""

 

    def __init__(self, filepath: str = "trajectory_error_data.csv",

                 encoding: str = "utf-8"):

        self.filepath = Path(filepath)

        self.encoding = encoding

 

    def load(self) -> pd.DataFrame:

        if not self.filepath.exists():

            raise FileNotFoundError(self.filepath)

        df = pd.read_csv(self.filepath, encoding=self.encoding)

        req = ["record_id", "distance_m", "error_mm", "speed_mm_s",

               "payload_kg", "temp_c"]

        miss = [c for c in req if c not in df.columns]

        if miss:

            raise ValueError(f"缺列: {miss}")

        # 类型转换

        num_cols = ["distance_m", "error_mm", "speed_mm_s",

                    "payload_kg", "temp_c"]

        for c in num_cols:

            df[c] = pd.to_numeric(df[c], errors="coerce")

        df = df.dropna(subset=["distance_m", "error_mm"]).reset_index(drop=True)

        return df

 

    def summary(self, df: pd.DataFrame) -> str:

        s = f"记录总数: {len(df)}\n"

        s += f"距离范围: {df['distance_m'].min():.1f} - {df['distance_m'].max():.1f} m\n"

        s += f"误差范围: {df['error_mm'].min():.3f} - {df['error_mm'].max():.3f} mm\n"

        s += f"速度范围: {df['speed_mm_s'].min():.0f} - {df['speed_mm_s'].max():.0f} mm/s\n"

        s += f"负载范围: {df['payload_kg'].min():.1f} - {df['payload_kg'].max():.1f} kg"

        return s

 

</details>

 

<details>

 

<summary></summary>

 

"""特征工程 (pandas + numpy)"""

 

import numpy as np

import pandas as pd

from typing import Dict, List

 

 

class FeatureEngineer:

    """构造回归特征"""

 

    def __init__(self, max_degree: int = 3):

        self.max_degree = max_degree

 

    def engineer(self, df: pd.DataFrame) -> pd.DataFrame:

        result = df.copy()

        # 多项式特征: distance^m

        for d in range(2, self.max_degree + 1):

            result[f"distance_m^{d}"] = result["distance_m"] ** d

        # 速度分组

        result["speed_low"] = (result["speed_mm_s"] < 300).astype(int)

        result["speed_high"] = (result["speed_mm_s"] > 800).astype(int)

        # 负载分组

        result["payload_heavy"] = (result["payload_kg"] > 5.0).astype(int)

        # 温度偏移(以22℃为基准)

        result["temp_deviation"] = result["temp_c"] - 22.0

        return result

 

    def get_feature_columns(self, df: pd.DataFrame) -> List[str]:

        """返回用于回归的特征列"""

        exclude = ["record_id", "error_mm"]

        return [c for c in df.columns if c not in exclude]

 

    def get_polynomial_features(self, distance: float,

                                degree: int = 2) -> np.ndarray:

        """为单个距离值生成多项式特征向量"""

        features = [1.0, distance] # 偏置 + 一次项

        for d in range(2, degree + 1):

            features.append(distance ** d)

        return np.array(features).reshape(1, -1)

 

</details>

 

<details>

 

<summary></summary>

 

"""回归建模 (scikit-learn)"""

 

import numpy as np

from typing import Dict, List, Tuple

from sklearn.linear_model import Ridge, LinearRegression

from sklearn.preprocessing import PolynomialFeatures, StandardScaler

from sklearn.pipeline import Pipeline

from sklearn.model_selection import cross_val_score

import pandas as pd

 

 

class RegressionModeler:

    """多项式Ridge回归 + 线性基线"""

 

    def __init__(self, alpha: float = 1.0, cv: int = 5):

        self.alpha = alpha

        self.cv = cv

        self.ridge_model_ = None

        self.linear_model_ = None

        self.best_degree_ = 2

        self.cv_results_ = {}

 

    def fit_ridge(self, X: np.ndarray, y: np.ndarray,

                  degree: int = 2) -> Pipeline:

        """Ridge 回归(带多项式展开+标准化)"""

        pipeline = Pipeline([

            ("poly", PolynomialFeatures(degree=degree, include_bias=False)),

            ("scaler", StandardScaler()),

            ("ridge", Ridge(alpha=self.alpha, random_state=42)),

        ])

        pipeline.fit(X.reshape(-1, 1) if X.ndim == 1 else X, y)

        self.ridge_model_ = pipeline

        return pipeline

 

    def fit_linear(self, X: np.ndarray, y: np.ndarray) -> LinearRegression:

        """线性基线"""

        lin = LinearRegression()

        lin.fit(X.reshape(-1, 1) if X.ndim == 1 else X, y)

        self.linear_model_ = lin

        return lin

 

    def compare_degrees(self, X: np.ndarray, y: np.ndarray,

                        max_degree: int = 4) -> Dict:

        """对比不同多项式阶数"""

        results = {}

        X_1d = X.reshape(-1, 1) if X.ndim > 1 else X

        for d in range(1, max_degree + 1):

            pipeline = Pipeline([

                ("poly", PolynomialFeatures(degree=d, include_bias=False)),

                ("scaler", StandardScaler()),

                ("ridge", Ridge(alpha=self.alpha, random_state=42)),

            ])

            scores = cross_val_score(pipeline, X_1d, y,

                                    cv=self.cv, scoring="r2")

            results[d] = {

                "mean_r2": float(scores.mean()),

                "std_r2": float(scores.std()),

            }

            if scores.mean() > results.get(self.best_degree_, {}).get("mean_r2", -999):

                self.best_degree_ = d

        self.cv_results_ = results

        return results

 

    def predict(self, X: np.ndarray) -> np.ndarray:

        """预测"""

        if self.ridge_model_ is None:

            raise ValueError("模型未训练")

        return self.ridge_model_.predict(X)

 

    def predict_with_interval(self, X: np.ndarray,

                               y_train: np.ndarray,

                               X_train: np.ndarray,

                               confidence: float = 0.95) -> Tuple:

        """预测 + 置信区间(简化版)"""

        pred = self.predict(X)

        # 基于训练残差估计标准差

        train_pred = self.predict(X_train)

        residuals = y_train - train_pred

        sigma = np.std(residuals)

        # 正态近似

        from scipy import stats

        z = stats.norm.ppf((1 + confidence) / 2)

        margin = z * sigma

        return pred, pred - margin, pred + margin, sigma

 

</details>

 

<details>

 

<summary></summary>

 

"""模型评估 (scipy + sklearn)"""

 

import numpy as np

from typing import Dict

from scipy import stats

from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error

 

 

class ModelEvaluator:

    """回归模型评估"""

 

    def __init__(self):

        pass

 

    def evaluate(self, y_true: np.ndarray,

                 y_pred: np.ndarray) -> Dict:

        """计算评估指标"""

        r2 = r2_score(y_true, y_pred)

        mse = mean_squared_error(y_true, y_pred)

        rmse = np.sqrt(mse)

        mae = mean_absolute_error(y_true, y_pred)

        residuals = y_true - y_pred

        # 残差正态性检验

        shapiro_stat, shapiro_p = stats.shapiro(residuals)

        # Durbin-Watson (自相关)

        dw = self._durbin_watson(residuals)

        return {

            "r2": round(r2, 4),

            "mse": round(mse, 6),

            "rmse": round(rmse, 4),

            "mae": round(mae, 4),

            "shapiro_stat": round(shapiro_stat, 4),

            "shapiro_p": round(shapiro_p, 6),

            "durbin_watson": round(dw, 4),

            "residuals": residuals,

        }

 

    def _durbin_watson(self, residuals: np.ndarray) -> float:

        """Durbin-Watson 统计量"""

        diff = np.diff(residuals)

        dw = np.sum(diff ** 2) / np.sum(residuals ** 2)

        return dw

 

    def feature_importance(self, model, feature_names: list) -> Dict:

        """提取特征系数"""

        importance = {}

        try:

            # 从 pipeline 中提取 ridge

            if hasattr(model, "named_steps"):

                ridge = model.named_steps.get("ridge")

                poly = model.named_steps.get("poly")

                if ridge is not None and hasattr(ridge, "coef_"):

                    coefs = ridge.coef_

                    if poly is not None:

                        names = poly.get_feature_names_out(feature_names)

                    else:

                        names = feature_names

                    for name, coef in zip(names, coefs):

                        importance[name] = abs(float(coef))

            else:

                # 直接是 LinearRegression

                if hasattr(model, "coef_"):

                    for name, coef in zip(feature_names, model.coef_):

                        importance[name] = abs(float(coef))

        except Exception:

            pass

        return dict(sorted(importance.items(),

                         key=lambda x: abs(x[1]), reverse=True))

 

</details>

 

<details>

 

<summary></summary>

 

"""可视化 (matplotlib + networkx)"""

 

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

import networkx as nx

 

plt.rcParams["font.sans-serif"] = ["SimHei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

 

 

class TrajectoryVisualizer:

    def __init__(self, results_dir: str = "results"):

        self.results_dir = Path(results_dir)

        self.results_dir.mkdir(exist_ok=True)

 

    def scatter_regression(self, X: np.ndarray, y: np.ndarray,

                           y_pred: np.ndarray,

                           best_degree: int, r2: float):

        """距离-误差散点+回归曲线"""

        fig, ax = plt.subplots(figsize=(10, 7))

        ax.scatter(X, y, c="#3498DB", alpha=0.6, s=50,

                  edgecolors="black", linewidth=0.5,

                  label="实际误差", zorder=3)

        # 排序画曲线

        X_sorted = np.sort(X.flatten())

        ax.plot(X_sorted, y_pred[np.argsort(X.flatten())],

               "r-", linewidth=2.5, label=f"Ridge 拟合 (deg={best_degree})",

               zorder=4)

        ax.set_xlabel("运行距离 (m)", fontsize=12)

        ax.set_ylabel("定位误差 (mm)", fontsize=12)

        ax.set_title(f"运行距离 vs 定位误差 (R²={r2:.3f})",

                    fontsize=13, fontweight="bold")

        ax.legend(fontsize=11)

        ax.grid(alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"scatter_regression.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def residual_analysis(self, residuals: np.ndarray,

                          shapiro_p: float):

        """残差分析"""

        fig, axes = plt.subplots(1, 2, figsize=(14, 6))

        # 残差直方图

        axes[0].hist(residuals, bins=15, color="#3498DB",

                    edgecolor="black", alpha=0.7, density=True)

        mu, sigma = np.mean(residuals), np.std(residuals)

        x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)

        from scipy import stats

        axes[0].plot(x, stats.norm.pdf(x, mu, sigma), "r-", linewidth=2,

                    label="正态拟合")

        axes[0].axvline(0, color="red", linestyle="--", linewidth=1.5)

        axes[0].set_xlabel("残差 (mm)")

        axes[0].set_ylabel("密度")

        axes[0].set_title(f"残差分布 (Shapiro p={shapiro_p:.4f})",

                         fontsize=11, fontweight="bold")

        axes[0].legend()

        axes[0].grid(alpha=0.3)

        # Q-Q 图

        stats.probplot(residuals, dist="norm", plot=axes[1])

        axes[1].set_title("Q-Q 图", fontsize=11, fontweight="bold")

        axes[1].grid(alpha=0.3)

        plt.suptitle("残差分析", fontsize=14, fontweight="bold")

        plt.tight_layout()

        plt.savefig(self.results_dir/"residual_analysis.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def feature_coefficients(self, importance: Dict):

        """特征系数条形图"""

        fig, ax = plt.subplots(figsize=(10, 6))

        names = list(importance.keys())[:8]

        vals = [importance[n] for n in names]

        colors = plt.cm.viridis(np.array(vals) / max(vals))

        ax.barh(range(len(names)), vals[::-1], color=colors[::-1],

               edgecolor="black", height=0.6)

        ax.set_yticks(range(len(names)))

        ax.set_yticklabels(names[::-1], fontsize=10)

        ax.set_xlabel("系数绝对值")

        ax.set_title("特征重要性 (系数绝对值)", fontsize=13, fontweight="bold")

        ax.grid(axis="x", alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"feature_coefficients.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def degree_comparison(self, cv_results: Dict):

        """多项式阶数对比"""

        fig, ax = plt.subplots(figsize=(8, 6))

        degrees = list(cv_results.keys())

        means = [cv_results[d]["mean_r2"] for d in degrees]

        stds = [cv_results[d]["std_r2"] for d in degrees]

        ax.bar(degrees, means, yerr=stds, color="#3498DB",

               edgecolor="black", alpha=0.8, capsize=8)

        ax.set_xticks(degrees)

        ax.set_xlabel("多项式阶数")

        ax.set_ylabel("交叉验证 R²")

        ax.set_title("多项式阶数 vs 模型性能", fontsize=13, fontweight="bold")

        ax.grid(axis="y", alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"degree_comparison.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def prediction_band(self, X: np.ndarray, y_pred: np.ndarray,

                        lower: np.ndarray, upper: np.ndarray):

        """预测误差带"""

        fig, ax = plt.subplots(figsize=(10, 7))

        X_sorted = np.sort(X.flatten())

        idx = np.argsort(X.flatten())

        ax.plot(X_sorted, y_pred[idx], "b-", linewidth=2.5,

               label="预测均值", zorder=3)

        ax.fill_between(X_sorted, lower[idx], upper[idx],

                       alpha=0.2, color="blue", label="95% 置信区间")

        ax.set_xlabel("运行距离 (m)", fontsize=12)

        ax.set_ylabel("预测定位误差 (mm)", fontsize=12)

        ax.set_title("定位误差预测带", fontsize=13, fontweight="bold")

        ax.legend(fontsize=11)

        ax.grid(alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"prediction_band.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def inference_network(self):

        """推理链路网络"""

        fig, ax = plt.subplots(figsize=(12, 8))

        G = nx.DiGraph()

        nodes = [

            ("原始数据", "input"),

            ("特征工程", "process"),

            ("多项式展开", "process"),

            ("标准化", "process"),

            ("Ridge回归", "model"),

            ("误差预测", "output"),

            ("置信区间", "output"),

        ]

        for n, nt in nodes:

            G.add_node(n, ntype=nt)

        edges = [

            ("原始数据", "特征工程"),

            ("特征工程", "多项式展开"),

            ("多项式展开", "标准化"),

            ("标准化", "Ridge回归"),

            ("Ridge回归", "误差预测"),

            ("Ridge回归", "置信区间"),

        ]

        G.add_edges_from(edges)

        pos = nx.spring_layout(G, seed=42, k=2)

        color_map = {

            "input": "#3498DB", "process": "#F39C12",

            "model": "#9B59B6", "output": "#27AE60"

        }

        node_colors = [color_map[G.nodes[n]["ntype"]] for n in G.nodes()]

        nx.draw_networkx_nodes(G, pos, node_color=node_colors,

                              node_size=2500, alpha=0.85, ax=ax)

        nx.draw_networkx_edges(G, pos, arrows=True, arrowsize=15,

                              edge_color="gray", alpha=0.6, ax=ax)

        nx.draw_networkx_labels(G, pos, font_size=9, ax=ax)

        ax.set_title("推理链路", fontsize=14, fontweight="bold")

        ax.axis("off")

        plt.tight_layout()

        plt.savefig(self.results_dir/"inference_network.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

</details>

 

<details>

 

<summary></summary>

 

"""合成机器人轨迹误差数据"""

 

import numpy as np

import pandas as pd

from pathlib import Path

from typing import Optional

 

 

class SyntheticTrajectoryGenerator:

    """

    80条轨迹误差记录

    误差 = 0.05 + 0.08×d + 0.03×d² + 噪声

    """

 

    def __init__(self, rng: Optional[np.random.RandomState] = None):

        self.rng = rng or np.ran

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐