首页
关于
Search
1
同步本地Markdown至Typecho站点
54 阅读
2
微服务
38 阅读
3
苍穹外卖
27 阅读
4
JavaWeb——后端
24 阅读
5
消息队列MQ
18 阅读
后端学习
项目
杂项
科研
论文
默认分类
登录
推荐文章
推荐
拼团设计模式
项目
8月11日
0
7
0
推荐
拼团交易系统
项目
6月20日
0
21
1
推荐
Smile云图库
项目
6月7日
0
27
0
热门文章
54 ℃
同步本地Markdown至Typecho站点
项目
3月22日
0
54
0
38 ℃
微服务
后端学习
3月21日
0
38
0
27 ℃
苍穹外卖
项目
3月21日
0
27
0
最新发布
2025-09-08
K8S
Kubernetes (K8S) Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩缩容(Pod 数量多了/少了自动调整)和自愈(坏掉的 Pod 会被自动重建) 基本架构 一个 Kubernetes 集群 (Cluster) = 控制平面 + 工作节点 的组合。要使用K8S,要先搭建集群,deployment.yaml 和 service.yaml 要提交到 K8S 集群,由它调度和运行。 控制平面 (Control Plane) 负责管理整个集群,不直接跑应用。 组件 作用 比喻 API Server 接收命令(kubectl)、提供统一接口 前台服务员 etcd 存储集群所有状态(配置、Pod 列表等) 账本/数据库 Scheduler 决定 Pod 跑在哪个 Node 上 领班 Controller Manager 保证实际状态符合预期(补 Pod、重建失败的 Pod) 经理 工作节点 (Worker Nodes) 实际跑应用容器。 组件 作用 Kubelet 负责跟 API Server 沟通,并启动/管理容器 容器运行时 运行容器(Docker、containerd) Kube-Proxy 管理网络规则,实现 Service 的负载均衡 graph TD A[控制平面] --> B[Node 1] A --> C[Node 2] A --> D[Node 3] B --> E[Pod] B --> F[Pod] C --> G[Pod] D --> H[Pod] K8S 核心概念 Pod 最小运行单元,一个 Pod 里可以有 1 个或多个容器。 共享网络和存储空间 Deployment 管 Pod 的「副本数」和「版本」。 支持滚动更新、回滚 Service 提供稳定的网络入口(因为 Pod IP 会变)。 负载均衡到一组 Pod。 ConfigMap & Secret ConfigMap:存储配置信息(非敏感)。 Secret:存储敏感信息(密码、Token),会加密。 基本使用方式 Deployment(定义 Pod 模板 + 副本数) apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 3 # 要 3 个 Pod selector: matchLabels: app: my-app template: # Pod 模板 metadata: labels: app: my-app #给 Pod 打标签,Service 用 selector 找到这些 Pod 做负载均衡 spec: containers: - name: my-app #Pod名 image: my-registry/my-app:v1 # ← 指向 CI 推送后的镜像(仓库/名称:标签) ports: - containerPort: 8080 #容器对外提供服务的端口 Pod名可能是:my-app-6f7c9d7c5d-abcde,它里面的容器名:my-app 映射关系: kind: Deployment → 创建一个「Pod 管理器」 replicas: 3 → 保证始终有 3 个 Pod template → Pod 的样子(运行哪个镜像、开哪个端口) Service(提供统一访问入口) apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: my-app # 找到所有带 app=my-app 标签的 Pod ports: - port: 80 # Service 入口端口 targetPort: 8080 # Pod 里容器的端口 type: LoadBalancer # 暴露给外部访问 映射关系: selector → 绑定到 Deployment 创建的 Pod,根据 Pod 的标签(my-app) ports → 用户访问 80 端口,会转发到 Pod 的 8080 type: LoadBalancer → 提供一个外部 IP 供用户访问 典型工作流程 sequenceDiagram 开发者->>Git: 提交代码 Git->>CI/CD: 触发构建 CI/CD->>镜像仓库: 构建Docker镜像 CI/CD->>K8S: kubectl apply K8S->>K8S: 创建/更新Pod K8S->>K8S: 健康检查 K8S->>用户: 服务可用 sequenceDiagram 开发者->>API Server: kubectl apply -f xxx.yaml API Server->>etcd: 写入期望状态 API Server->>Scheduler: 请求调度 Scheduler->>Node: 分配 Pod 到合适的节点 Node->>Kubelet: 启动容器 Controller Manager->>Cluster: 监控状态并修复 Service->>用户: 提供统一访问入口 👉 过程总结: 提交 YAML → API Server 接收并存到 etcd。 Scheduler 决定 Pod 去哪个 Node。 Node 上的 Kubelet 把容器启动。 Controller Manager 盯着数量,缺了就补。 Service 统一出口,用户不用关心 Pod IP。 常用操作 前提是1:集群必须已经搭好(minikube/kind/k3s/云厂商的 K8S)。 2:kubectl 已经配置好 kubeconfig 3:镜像能拉取到 如果是公有镜像(比如 Docker Hub),直接写就行。 如果是私有仓库,需要配 imagePullSecrets。 # 部署应用 kubectl apply -f deployment.yaml kubectl apply -f service.yaml # 查看集群资源 kubectl get pods -o wide kubectl get deployments kubectl get services # 扩缩容 kubectl scale deployment/my-app --replicas=5 # 滚动更新 kubectl set image deployment/my-app my-app=my-registry/my-app:v2 # 回滚 kubectl rollout undo deployment/my-app
杂项
zy123
9月8日
0
1
0
2025-09-06
CICD
CI/CD 自动部署项目 使用Gitea Actions 1)启用Gitea Actions: 编辑你的Gitea服务器配置文件 app.ini(通常位于 /etc/gitea/或 Gitea 安装目录),添加: [actions] ENABLED = true 然后重启Gitea服务。 2)在部署服务器上安装Runner: # 1. 下载并安装 act_runner (需要sudo) sudo wget https://gitea.com/gitea/act_runner/releases/download/v0.2.10/act_runner-0.2.10-linux-amd64 -O /usr/local/bin/act_runner sudo chmod +x /usr/local/bin/act_runner # 2. 为Runner创建专用工作目录(推荐使用绝对路径) sudo mkdir -p /opt/gitea-runner sudo chown $USER:$USER /opt/gitea-runner # 将目录所有权给当前用户 cd /opt/gitea-runner # 3. 注册Runner(重要:必须添加labels标签) act_runner register --no-interactive \ --instance https://你的gitea域名.com \ --token <你的令牌> \ --name my-runner \ --labels self-hosted,linux # 这个标签必须与工作流文件中的runs-on匹配 # 4. 启动Runner(后台运行) nohup act_runner daemon > runner.log 2>&1 & # 5. 查看运行状态和日志 tail -f runner.log ps aux | grep act_runner 3)令牌获取: 如果你想给整个实例用 → 站点管理员设置 → Actions → Runners。 如果只想给某个仓库用 → 进入该仓库 → Settings → Actions → Runners。 点击 New Runner,系统会生成一个 TOKEN。 例如:abcdef1234567890 还是设置整个实例好!! 4)将act_runner注册为服务自启动 sudo vim /etc/systemd/system/act_runner.service 写入以下内容: [Unit] Description=Gitea Actions Runner After=network.target [Service] ExecStart=/usr/local/bin/act_runner daemon WorkingDirectory=/opt/gitea-runner User=zy123 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ExecStart 指向你安装的 act_runner 路径(你已经放在 /usr/local/bin/ 了)。 WorkingDirectory 可以写你打算存放 Runner 缓存的目录(比如 /home/zy123/act_runner,你已经在这里 register 过了)。 User=zy123 保证 Runner 以你当前用户运行,而不是 root。 重新加载 systemd 配置: sudo systemctl daemon-reexec 启动并开机自启: sudo systemctl enable --now act_runner 查看运行状态: systemctl status act_runner 5)在后端仓库根目录下,新建目录和文件: .gitea/workflows/deploy.yml 写入以下内容: name: Deploy Backend on: push: branches: [ "master" ] # master 分支推送时触发 jobs: build-and-deploy: runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v3 - name: Create application-local.yml run: | mkdir -p src/main/resources/ cat << 'EOF' > src/main/resources/application-local.yml ${{ secrets.APPLICATION_LOCAL_YML }} EOF - name: Build and restart smile-picture run: | cd docs/tags/picture-v1.0 docker compose -f docker-compose-app-v1.0.yml build smile-picture-backend docker compose -f docker-compose-app-v1.0.yml up -d smile-picture-backend - name: Cleanup dangling images run: docker image prune -f 特别注意,application-local没有用git管理,把它存在了Actions的密钥中: 然后deploy.yml中可以把里面的内容复制过去。 6)工作原理 1.Runner 接收任务 当你 push 到 main 分支时: Gitea 会触发 workflow(.gitea/workflows/deploy.yml)。 服务器上的 act_runner 会接收到这个任务,并开始执行 jobs.build-and-deploy。 2.actions/checkout@v3 这一行的作用是:它会把你刚刚 push 的最新代码 完整克隆 到 Runner 的工作目录。 /home/<你的用户>/actions-runner/_work/<repo名>/<repo名>/ 所以,这时候你的项目在 Runner 的临时目录里已经是最新代码了,不需要 git pull。 3.后续 cd docs/tag/group-buy-v3.0 都是在 这个临时目录 里执行的。 相当于你在服务器上的临时副本中: 用 docker compose build 构建镜像 用 docker compose up -d 启动/更新容器 4.Runner 每次执行 workflow 时,工作目录都会 重新 checkout 最新代码。 默认不会自动清理旧目录,但可以在 workflow 里加 actions/checkout 的参数来控制,比如 clean: true。. 7)git push之后
杂项
zy123
9月6日
0
3
0
2025-08-31
训练神经网络
🧠 神经网络训练流程基础笔记 1. 数据集(Dataset) 数据集包含了 样本 (sample) 和 标签 (label) 在你的场景里: 样本 = 一个时间步的图(节点特征矩阵 + 邻接矩阵) 标签 = 每个节点是否掉线(0/1) 2. Batch(批量) Batch = 一次训练用到的一小部分样本 batch_size 表示 每次梯度更新时用多少个样本 例如: 数据集有 1000 个样本 batch_size=8 → 每次训练只拿 8 个样本来算梯度 这样能减少显存占用,也让模型更新更频繁 3. Epoch(轮次) Epoch = 把整个数据集完整训练一遍 如果: 数据集有 1000 个样本 batch_size=8 那么 1 个 epoch 需要 1000 / 8 = 125 次迭代,才能用完所有样本 训练 20 个 epoch,就相当于把数据重复“看”了 20 遍 4. 训练循环流程 一次完整训练过程一般是这样: 初始化模型参数(随机权重) 重复若干 epoch 打乱训练数据 按 batch_size 切成小批次 对每个 batch: 前向传播 (forward) 把输入样本丢进模型 得到预测结果 计算损失 (loss) 预测 vs 真实标签 的差距 反向传播 (backward) 自动求导,算出梯度 参数更新 (step) 用优化器(SGD/Adam)更新参数,让模型预测更接近标签 最终得到训练好的模型 5. 为什么要用 batch? 全量训练 (batch_size=1000) 优点:精确 缺点:显存占用大,更新慢 小批量训练 (batch_size=8~32) 优点:节省显存,更新更频繁,收敛快 缺点:梯度有点“噪声”(但通常能帮助模型泛化) 👉 所以主流方法是 小批量训练 + 多个 epoch。 6. 直观理解 把训练比作 学生背单词: 样本 = 单词 batch_size = 一次背多少个单词(8 个单词一组,还是 50 个单词一组) epoch = 把词表完整过一遍(1000 个单词都背一遍) 多个 epoch = 重复背很多遍(记得更牢) 7. 在你现在的任务中 数据:1000 时间步 batch_size=8 → 一次训练 8 个时间步的图 epochs=20 → 每个时间步都要用到,整个过程重复 20 遍 总共更新参数的次数 = 1000/8 * 20 = 2500 次 📌 一句话总结: 训练神经网络 = 前向传播(算预测) + 损失函数(算误差) + 反向传播(算梯度) + 参数更新(优化器) 重复这个过程,按 batch 分批喂数据,按 epoch 控制重复多少轮。
科研
zy123
8月31日
0
3
0
2025-08-29
仿真数据模拟
高斯马尔科夫(有点关联) RWP(没有关联) 静态网络 节点移动模型 节点移动模型 模拟随机网络中节点的移动方式,进而间接模拟网络拓扑在不同时刻的变化。它们是用来在仿真环境下产生“网络结构随时间动态变化”的数据,从而让后续的网络重构或网络分析算法有一个逼近真实场景的测试环境。 RW(Random Walk,随机游走)模型 基本概念:在 随机游走(RW) 模型中,节点在一个定义的区域内随即选择方向并开始移动。每当节点到达区域的边界时,它会反弹并继续前进。节点的移动时间是固定的,且每个移动步骤都是独立的。 特点 节点移动过程中,节点的行进方向是完全随机的。 节点在到达区域边界时会选择一个新的角度进行反弹,并继续随机移动。 节点的移动是不规则的,每次运动的时间或距离是固定的,直到达到边界。 适用场景:适用于需要模拟节点在空间中随机漂移或无规律移动的场景,如某些类型的无人机网络或粒子运动模型。 RD(Random Direction,随机方向)模型 基本概念:在 随机方向(RD) 模型中,节点每次选择一个随机的方向,并在该方向上移动直到达到区域的边界。到达边界后,节点会随机选择一个新的目标方向,并继续移动。 特点 节点在每个时间片段内选择一个随机的方向,而不是随机选择目标。 节点在到达边界时会停留一段时间,然后选择一个新的随机方向。 该模型中,节点的运动行为更有方向性,与RW模型相比有更强的运动规律性。 适用场景:适用于需要模拟节点在特定方向上移动的情况,如某些类型的车载网络或定向通信网络。 RWP(Random Waypoint,随机路点)模型 基本概念:在 随机路点(RWP) 模型中,节点选择一个随机的位置作为目标点,然后以固定速度沿直线移动到该位置。到达目标点后,节点选择一个新的随机目标位置,并再次以相同的速度移动。 特点 节点移动到随机选定的目标位置,并在到达后停留一段时间。 该过程重复进行,每次都选择新的随机目标位置。 节点在任意时刻都有一个目标位置,而不是随机选择一个方向。 适用场景:适用于模拟节点有明确目标且周期性移动的网络场景,比如无线传感器网络和移动广告网络等。 参数 节点数量决定了在该活动半径内随机分布并移动的节点数量 通信半径 决定了网络中“谁能跟谁连边”,对 拓扑连通性 影响极大(如果两节点之间的距离小于等于通信半径,就认为它们之间存在连边); 活动半径 决定了节点分布和移动范围,对 网络整体的稀疏/稠密程度、节点之间的平均距离都有重要影响。 仿真流程说明 RWP 移动模型驱动 你首先用 RWP (Random Waypoint) 模型生成节点在二维平面上的轨迹。 输入参数:节点数、活动区域半径、最小/最大速度、停留时间、总步数。 输出:每个时刻 pos(t) (节点坐标) 与 vel(t) (节点速度)。 边特征计算 (Link Features) 根据节点的相对位置、速度、信道参数,生成 10 种边特征矩阵 信道相关:SNR、容量、时延、可靠性。 几何相关:距离反比、相对速度、LET。 统计相关:SNR 梯度、SNR 波动。 网络相关:干扰指数。 每个特征是一个 (N×N) 矩阵,表示任意两节点之间的链路特性。 边→节点聚合 (Edge → Node) 使用 edge_to_node_features 将边特征转化为节点特征。 聚合策略: 归一化到 0–1 区间。 用可靠性 (Rel) 或邻居数作为权重,做加权均值。 对关键特征(SNR、容量、时延、可靠性、LET)额外计算最大值、标准差、软计数。 附加结构性特征(节点度数、可靠邻居数)。 节点特征时序 (Time Series) 在多个时刻重复上述过程。 得到最终张量: node_feats.shape = (T, N, F) T:生成帧数(由 steps 和 take_every 决定)。 N:节点数。 F:每个节点的特征维度(几十个)。 RWP 移动模型如何驱动这些指标 节点移动 (RWP) → 距离 & 速度变化 距离 & 速度 → SNR、容量、时延、可靠性、LET、干扰等变化 时间演化 & 历史 → SNR 梯度、SNR 波动、AoI 所有链路和节点特征都被 RWP 模型动态驱动。 1. SNR / SINR (信噪比/信干噪比) 作用:衡量链路“干净程度”。SNR 只考虑热噪声;SINR 同时把同频干扰算进来(更真实)。 如何读:高→更容易解调、误码率更低。低→链路脆弱/不稳定。 驱动因素:节点间距离随 RWP 变化 → 路径损耗变化 → 接收功率变化 → SNR 随时间变化。 公式 路径损耗(自由空间 + 阴影衰落): $PL(dB) = 32.44 + 20 \log_{10}(d_{km}) + 20 \log_{10}(f_{MHz}) + X_\sigma$ 接收功率: $P_r(dBm) = P_t + G_t + G_r - PL(dB)$ 噪声功率: $N(dBm) = -174 + 10 \log_{10}(B) + NF$ 信噪比(线性 / dB): $\gamma = \frac{P_r}{N + I}, \quad SNR_{dB} = 10\log_{10}(\gamma)$ 2. 容量 (Capacity) 作用:理论上该链路在当前 SNR 下能承载的最大信息速率。 如何读:高→更快的数据吞吐。受带宽和 SNR 决定。 驱动因素:由 SNR 决定,SNR 随节点距离移动而变化。 公式: $C = B \cdot \log_2(1 + \gamma) \quad [bps]$ 转换为 Mbps: $C_{Mbps} = \frac{C}{10^6}$ 3. 时延 (Latency) 作用:端到端“一包数据”平均要花多少时间传完。 如何读:低→交互更流畅;高→拥塞/距离/低容量导致的排队或传输时间变长。 驱动因素:随距离变化(传播时延)、随链路容量变化(传输时延)、随负载变化(排队时延)。 公式 端到端总时延 $D$ 的计算公式如下: $$D = \underbrace{\frac{L}{C}}{\text{传输时延}} + \underbrace{\frac{d}{c}}{\text{传播时延}} + \underbrace{D_q}_{\text{排队时延}}$$ 其中: $L$:包长(比特数) $C$:容量(bps) $d$:节点间距离 $c$:光速 $D_q \approx \alpha (C_{\max} - C)/C_{\max}$ 4. 距离反比权 (InvDist) 作用:把“越近越可能连得好”的直觉,转成一个简单的图权重。 如何读:数值大→更近;指数/倒数两种形式都只是启发式。 驱动因素:节点间距离 $d$ 随 RWP 移动而变化。 公式(二选一) 线性: $w_{ij} = \frac{1}{d_{ij} + \epsilon}$ 或指数: $w_{ij} = e^{-\alpha d_{ij}}$ 5. 可靠性 (Reliability) 作用:一次发送“整包成功”的概率(由误码率推得)。 如何读:高→少重传、稳定;随 SNR 升、距离降而提高;包长越大越“难保真”。 驱动因素:依赖 SNR,随节点距离变化。 公式 (QPSK 近似): 比特错误率 (BER): $BER \approx 0.5 \cdot e^{-\gamma}$ 分组错误率 (PER): $PER = 1 - (1 - BER)^L$ 可靠性: $R = 1 - PER$ 6. 相对速度 (Relative Speed) 作用:两个节点的速度差大小,反映“分离趋势/接近速度”。 如何读:大→拓扑变化快、链路寿命短;小→更稳定。 驱动因素:节点速度向量 $V_i$ 随 RWP 改变。 公式: $v_{rel}(i,j) = | V_i - V_j |$ 7. 链路到期时间 (LET, Link Expiration Time) 作用:按当前相对位置/速度预测“距离超过通信半径前还能活多久”。 如何读:大→可持续更久;无正根时记为 +∞(意味着短期内不会因半径断链)。 驱动因素:节点位置 $P$、速度 $V$ 决定未来多久超出通信半径。 公式(解二次方程): $| (P_i - P_j) + (V_i - V_j)t |^2 = R^2$ 取正根 $t > 0$ 作为 LET。 8. SNR 梯度 (SNR_grad) 作用:SNR 的一阶差分,刻画“趋势”。 如何读:正→在变好(靠近/干扰减);负→在变差(远离/干扰增)。 驱动因素:历史 SNR 随时间变化。 公式: $\nabla SNR = SNR(t) - SNR(t-1)$ 9. SNR 波动 (SNR_std) 作用:最近 K 步的标准差,刻画“波动性/抖动”。 如何读:小→稳定;大→易抖,预测难、重传风险高。 驱动因素:取最近 $K$ 步的 SNR 序列,计算标准差。 公式: $\sigma_{SNR} = \text{std}{ SNR(t-K+1), \dots, SNR(t) }$ 10. 干扰指数 (Interference Index) 作用:衡量同频邻居带来的“潜在挤占”。两种口径: count:邻居数的启发式(无量纲),反映“人多是非多”的拥挤程度。 rx_power:把活跃邻居对接收端的线性功率求和(可直接进 SINR 分母),物理口径更一致。 如何读:高→更容易被别的链路“压制”,有效 SNR 下降。 驱动因素:邻居节点数量和分布随 RWP 改变。 公式(二选一) count:邻居数 $I_{ij} = \frac{#\text{neigh}(i) + #\text{neigh}(j)}{2}$ rx_power:活跃邻居的接收功率和 $I_{ij} = \frac{I_i + I_j}{2}, \quad I_i = \sum_{k \neq i} P_{k \to i}$ 符号 含义 单位 来源(代码/配置) 随时间变化? $P_i(t)$ 第 $i$ 个节点位置 m RWP 轨迹 get_rwp_traces → compute_velocities 时变 $V_i(t)$ 第 $i$ 个节点速度 m/s (或 m/步) 同上(由位置差分) 时变 $d_{ij}(t)$ 节点 $i,j$ 的距离 m pairwise_dist(P(t)) 时变 $R$ 通信半径 m comm_radius 不变 $cs_radius$ 载波侦听半径(干扰近似用) m cfg.cs_radius 不变 $f_{\text{MHz}}$ 载频 MHz cfg.fc_mhz 不变 $P_t$ 发射功率 dBm cfg.Pt_dbm 不变 $G_t, G_r$ 发/收天线增益 dB cfg.Gt_db, cfg.Gr_db 不变 $B$ 带宽 Hz cfg.B_hz 不变 $NF$ 噪声系数 dB cfg.NF_db 不变 $N$ 噪声功率 线性或 dBm 由 $B,NF$ 计算 不变 $X_\sigma(t)$ 阴影衰落 dB cfg.shadow_sigma_db + 随机 rng.normal 时变(且链路相关) $PL_{ij}(t)$ 路径损耗 dB 自由空间 + 阴影公式 时变(依 $d_{ij},X_\sigma$) $P_{r,ij}(t)$ 接收功率 dBm/线性 $P_t+G_t+G_r-PL$ 时变 $I_{ij}(t)$ 干扰功率(平均到 i/j) 线性功率 feature_neighbor_interference_index(rx_power 时) 时变(位置+活跃集) $\gamma_{ij}(t)$ SNR/SINR(线性) – $P_r/(N)$ 或 $P_r/(N+I)$ 时变 $\text{SNR}{ij}(t)$, $\text{SINR}{ij}(t)$ dB 形式 dB $10\log_{10}(\gamma)$ 时变 $C_{ij}(t)$ 香农容量 bps / Mbps $B\log_2(1+\gamma)$ 时变 $L$ 包长 bit cfg.pkt_bits 不变(可按场景改) $D_{ij}(t)$ 端到端时延 s / ms $\frac{L}{C}+\frac{d}{c}+D_q$ 时变 $D_q(t)$ 排队时延近似项 s / ms $\alpha (C_{\max}-C)/C_{\max}$,cfg.alpha_queue 时变(跟 $C$ 走) $v_{\text{rel},ij}(t)$ 相对速度幅值 m/s $|V_i - V_j|$ 时变 $\text{LET}_{ij}(t)$ 链路到期时间 s 解 $|(P_i-P_j)+(V_i-V_j)t|=R$ 的正根 时变 $\nabla \text{SNR}_{ij}(t)$ SNR 梯度 dB $SNR(t)-SNR(t-1)$ 时变(需历史) $\sigma_{\text{SNR},ij}(t)$ SNR 波动 dB 最近 $K$ 步 std,cfg.K_std 时变 $Rel_{ij}(t)$ 可靠性(整包成功概率) 0–1 $BER\to PER\to Rel$,依 $\gamma$ 与 $L$ 时变 $BER, PER$ 比特/分组错误率 – $BER\approx 0.5e^{-\gamma}$,$PER=1-(1-BER)^L$ 时变 $w_{ij}(t)$ 距离反比权 – $1/(d+\epsilon)$ 或 $e^{-\alpha d}$(cfg.eps_dist/alpha_dist) 时变 $active_prob$ 节点活跃概率 – active_prob(生成干扰用) 不变(统计设定) $c$ 光速 m/s 物理常数 不变 节点特征生成 A. 固定的结构特征(不看你传了哪些边特征) deg:度(邻居数,按 in_range 统计)。 good_deg_r>=X:只有当 mats 里有 Rel 才会加上。把 Rel 与阈值 rel_good_th 比较(默认 0.9),统计“可靠邻居数”。 这两个特征与 extra_stats_keys 无关,始终(或条件)生成。 B. 对每一张你传入的“边特征矩阵” 都会先生成: key_wmean:邻域加权均值(默认用 weights_key="Rel" 作为权 W;否则等权)。 这一步把边特征从 N×N 聚成 N×1。 如果 key 同时出现在 extra_stats_keys,还会额外再生成三种统计: key_max:邻域内的最大“得分”(已做 0–1 归一/同向映射后的值)。 key_std:邻域内“得分”的标准差(衡量波动/不均匀)。 key_softcnt@th:软计数(把“得分”经过 $\sigma((S-th)/\tau)$ 后求和,近似“好邻居数量”)。 $S$ —— 邻边“得分”(score),来自把原始边特征用 SCORERS[key] 映射到 0–1 同向区间后的矩阵元素。 在代码里:S = SCORERS[key](X) 再 S = np.where(in_range, S, np.nan)(只保留邻域内)。 $\text{th}$ —— “好”的阈值(threshold)。超过它就算“好”。 在代码里:p['th_good'],默认 0.6。 $\tau$ —— 平滑尺度(temperature/宽度)。越小越“硬”,越像 0/1 的硬阈值;越大越“软”。 在代码里:p['tau'],默认 0.08。 $\sigma(\cdot)$ —— logistic sigmoid 函数: $\sigma(z)=\frac{1}{1+e^{-z}}$ 输入任意实数,输出落在 $(0,1)$。在代码里就是 1/(1+np.exp(-z))。 “得分”= SCORERS[key](X):每个物理量先用代码里那套映射器(线性/指数/sigmoid 等)压到 0–1,同向化后再做这些统计。 打标签规则 标签定义 y_offline[t,i] ∈ {0,1}:节点 i 在时间 t 是否掉线(1=掉线,0=在线)。 另存:health[t,i] ∈ [0,1] 节点健康度(越大越好),便于解释/调参。 输入 来自 node_features.npz node_feats: (T, N, F) feat_names: (F,) 用到哪些特征 参与健康度均值的“0–1同向得分”特征: Rel_wmean, snr_db_wmean(或 sinr_db_wmean), C_Mbps_wmean, D_ms_wmean, InvDist_wmean, RelSpeed_wmean, LET_wmean, SNR_std_wmean(波动小→分高), Interf_wmean(干扰小→分高)。 结构特征: deg(已做 0–1 归一化)用于孤立判断; good_deg_ratio* 仅做参考,不参与健康度均值。 掉线判定 孤立触发:若 deg[t,i] ≤ iso_eps(默认 1e-3),立即掉线。 健康度触发 掉线阈 thr_down(默认 0.35):health < thr_down 连续 W_down 帧(默认 3)→ 掉线; 恢复阈 thr_up(默认 0.45):health > thr_up 连续 W_up 帧(默认 3),且非孤立 → 恢复在线。 注意:thr_up > thr_down 形成滞回区间,避免“抖动上线/下线”。 状态机流程: 上一帧在线:若「孤立」或「低健康度累计 W_down」→ 标为掉线; 上一帧掉线:若「高健康度累计 W_up 且非孤立」→ 标为在线;否则继续掉线。 外生故障 配置 use_exogenous_faults=True时,为每个节点注入“随机崩溃/修复”过程: 每帧以概率 lam_crash 触发崩溃,持续时长 ~ 指数/几何分布(期望 mean_repair 帧)。 只要外生故障激活,该节点直接掉线(与上述条件“取或”)。 有两个问题: 1.不同特征,它的数据范围是不同的,比如特征a分布区间在[0,0.3],而特征b在[0.5,0.7],简单将它们平均来计算健康度是不合理的,需要首先对每一维做对比度校准 2.thr_down和thr_up的选取,先计算出健康度 health,然后利用分位数设定 thr_down 和 thr_up,保证大约10%的节点处于掉线状态。
论文
zy123
8月29日
0
4
0
2025-08-29
草稿
好呀 👍 我来举一个具体的小例子,帮你直观理解 WL 测试是怎么迭代更新节点特征(颜色)的。 🌳 示例图 假设有一个小图: A / \ B C 初始节点特征: A: red B: blue C: blue 1️⃣ 初始状态 (Iteration 0) WL 测试开始时,每个节点用自己的初始特征(颜色)作为标签: A: red B: blue C: blue 2️⃣ 第 1 轮更新 (Iteration 1) 规则:新标签 = 节点自己的颜色 + 邻居颜色的集合 (然后哈希成一个新的颜色/编码) A 的邻居是 {B, C} = {blue, blue} → 新标签 = (red, {blue, blue}) B 的邻居是 {A} = {red} → 新标签 = (blue, {red}) C 的邻居是 {A} = {red} → 新标签 = (blue, {red}) 更新后: A: 新颜色 α B: 新颜色 β C: 新颜色 β 3️⃣ 第 2 轮更新 (Iteration 2) 继续相同规则: A 的邻居是 {B, C} = {β, β} → 新标签 = (α, {β, β}) B 的邻居是 {A} = {α} → 新标签 = (β, {α}) C 的邻居是 {A} = {α} → 新标签 = (β, {α}) 更新后: A: 新颜色 γ B: 新颜色 δ C: 新颜色 δ 🔎 观察结果 WL 的作用:它让节点的标签逐步编码了“以自己为根的邻居子树结构”。 A 的标签区分了“自己 + 两个相同邻居”。 B 和 C 的标签相同,因为它们对称,结构一样。 图区分性:如果换一个图(比如 B 和 C 不一样颜色),WL 会在某一轮产生不同的标签,从而区分两个图是否同构。 🤝 和 GIN 的联系 在 GIN 中,更新公式是: $h_v^{(k)} = \text{MLP}\Big((1+\epsilon)h_v^{(k-1)} + \sum_{u\in N(v)} h_u^{(k-1)}\Big)$ 这正好对应 WL 的“自己标签 + 邻居标签集合”,只不过: WL 用哈希函数更新 → 只能得到离散的“颜色”。 GIN 用 MLP → 得到连续向量,可以学习结构相似性。 要不要我再给你举一个 对比例子:用 WL 测试看看两个“非同构”的图(比如一条三节点链 vs 三角形)是如何在第二轮被区分开的?
论文
zy123
8月29日
0
5
0
1
2
...
12
下一页