咕咕鸽爱学习 - zy123
type: channel
link: https://bitday.top/author/1/
description: zy123
items: Cursor使用
items: deepwalk
items: 移动模型
items: K8S
items: CICD
items: 训练神经网络
items: 草稿
items: RAG知识库
items: 拼团设计模式
items: 测试

Cursor使用
type: item
date: 2025-10-29T11:45:02+08:00
description: Cursor 插件、环境安装 1）Chinese (Simplified) Language Pack，中文界面插件。 2）Extension Pack for Java 只要安装了 “Extension Pack for Java”，其它插件（Maven、Debugger、Language Support、Test Runner、Project Manager 等）都是它自动帮你装好的，不需要你一个个手动点安装。 这样打开项目文件夹（包含 pom.xml 的根目录）时： 它会自动检测项目类型 → 加载 Maven → 解析依赖。底部出现 Java: Ready、Building [Done]，说明依赖已经下载并索引完毕。默认使用的是系统环境变量MAVEN_HOME的地址。 或者在这里指定： 自动选择jdk版本： 查看pom中配置，Cursor 会用这个版本作为编译目标。 <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> 运行时版本由“系统环境或 Cursor 配置”决定，系统变量里的 JAVA_HOME，就是 你系统默认使用的 JDK。随便打开一个终端 java -version ，可以看到使用的是jdk17。 3） Spring Boot Extension Pack 左侧多出一个 Spring Boot Dashboard； 自动识别所有带 @SpringBootApplication 的项目； 可以直接在面板里点击 ▶️ 启动； application.yml会出现智能提示，比如： spring.datasource.url spring.datasource.username spring.datasource.password 4）IntelliJ IDEA Keybindings 装上它之后，你在 Cursor 里按的快捷键和 IDEA 几乎一样； 5）“Want to launch Cursor from the command line? You can add the code or cursor commands now, or later with Ctrl+Shift+P and typing ‘install code command’.” 这是一个 可选的小功能提示，翻译：“想要从命令行启动 Cursor 吗？你可以现在添加 code 或 cursor 命令，也可以之后按 Ctrl + Shift + P，输入 install code command 来添加。” 作用：直接通过命令行（例如 PowerShell、CMD、终端），打开项目或文件。 cursor . 表示： 用 Cursor 打开当前文件夹（.） 或者：cursor C:\project\group-buying-sys 表示： 用 Cursor 打开指定路径下的项目。 如何查看配置？ Ctrl+shift+P 快捷键，输入 open user settings 可以打开用户配置。 输入 project setting 可以打开项目配置文件 或者左下角JAVA PROJECTS，点击Configure JAVA Runtime： 运行JAVA项目 Maven编译 运行 1）打开启动类，点击run/debug 2） 编辑器界面 ┌────────────────────────────────────────────┐ │ 顶部菜单栏（File / 编辑 / 选择 / 查看...）│ ├────────────────────────────────────────────┤ │ 左侧侧边栏（文件树 / 项目 / Git 等） │ ├────────────────────────────────────────────┤ │ 中间主编辑区（代码编辑） │ ├────────────────────────────────────────────┤ │ 右侧 AI 面板（Cursor 智能助手 / Chat） │ ├────────────────────────────────────────────┤ │ …

deepwalk
type: item
date: 2025-09-20T22:03:49+08:00
description: DeepWalk DeepWalk 的最终目标是—— 把图中的每个节点，用一个低维向量表示（embedding）出来，使得结构相似的节点在向量空间中也接近。 也就是说，如果两个节点在图上经常“一起出现”（相连、同社群等），那它们的 embedding 也应该相似。 主要思想 将图结构转化为“序列语料”： 在图上做 随机游走（random walks），生成顶点序列，类似于自然语言中的“句子”。 将随机游走得到的序列输入 Skip-Gram 模型，学习节点的低维嵌入表示。 学到的嵌入能捕捉到 邻居相似性、社区结构，可用于分类、聚类、链路预测等任务。 输入 & 输出 输入：图结构 $G=(V,E)$，随机游走参数（步长 $t$，次数 $\gamma$，窗口大小 $w$），嵌入维度 $d$。 输出：节点嵌入矩阵 $\Phi \in \mathbb{R}^{|V|\times d}$。 关键公式与目标 随机游走生成“句子”： 从某个顶点 $v_i$ 出发，采样一个长度为 $t$ 的随机游走序列： $$ W_{v_i} = (v_i, v_{i+1}, \dots, v_{i+t}) $$ 生成的序列 $W_{v_i}$ 就是一句“话”，用来训练 Skip-Gram 模型。在这些序列中，如果两个节点经常在相邻位置出现，就表示它们关系密切。 ["A", "B", "C", "D"] Skip-Gram 目标函数： 现在我们用 Word2Vec 的思想：对于一句话 ["A", "B", "C", "D"]，假设窗口大小 $w = 1$，也就是每个节点只看它的邻居。那么训练样本是这样的： 中心节点 它要预测的邻居 A B B A, C C B, D D C 模型要学的是： “给我节点 B，我要能预测出 A 和 C。” “给我节点 C，我要能预测出 B 和 D。” 于是就有这个公式，给定中心节点 $v_i$，最大化其上下文窗口内邻居节点的条件概率： $$ \max_{\Phi} \sum_{i=1}^{|V|} \sum_{u \in \mathcal{N}_w(v_i)} \log Pr(u \mid \Phi(v_i)) $$ 其中 $\mathcal{N}_w(v_i)$ 表示在随机游走序列中，窗口大小 $w$ 内的上下文节点。 我希望模型能学到这样一种 embedding：中心节点 $v_i$ 能够高概率预测出它周围的邻居 $u$。 优化形式（负对数似然）： 就是把上面的最大化目标，改写成一个最小化损失函数。 最大化“好事”（邻居出现的概率）= 最小化“坏事”（邻居预测错误的概率） $$ \min_{\Phi} - \log Pr\big( {v_{i-w},\dots,v_{i+w}} \mid \Phi(v_i) \big) $$ 概率建模（Hierarchical Softmax 或 Negative Sampling）： $$ Pr(u \mid \Phi(v_i)) = \frac{\exp\big( \Phi(u) \cdot \Phi(v_i) \big)}{\sum_{v \in V} \exp\big( \Phi(v) \cdot \Phi(v_i) \big)} $$ 这相当于用 Softmax 把所有节点的相似度转成概率分布。 其中： 分子：中心节点和邻居节点的相似度（点积越大越相似）； 分母：所有节点的相似度和（用来归一化成概率）。 ​ 如果 $u$ 是 $v_i$ 的邻居，那么 $\Phi(u)$ 与 $\Phi(v_i)$ 的点积就应更大。 例子 想象你是个“社交分析师”： 你观察到小明每天都和小红、小刚一起出现； 而小明几乎从不和小李在一起； 那你自然会说：小明和小红、小刚的关系更近。 DeepWalk 就是通过“随机游走 + 预测邻居”这个机制， 自动学出“谁跟谁关系近”的数值表示。 训练逻辑 1）加载 10+1 张图 A_list = [A100, A101, ..., A110] 我们取前 10 张作为输入，最后一张作为真实标签。 2）对每一个时间步的图做 DeepWalk for t in range(100, 110): emb_t = DeepWalk(A_t) 每张图 $A_t$ 都独立训练一个 节点 embedding（比如 400×64）。 400是节点数，64是嵌入维数 embedding 就是每个节点在这一时刻的“语义坐标”。 训练目标是：让在图里常相邻的节点在 embedding 空间也靠得近。 可以理解成： DeepWalk 把图结构变成“节点的向量表示”。 3）拼接成时间序列特征（10步） 对每对节点 (i, j)，你把过去10个时间步的 embedding 拿出来，计算每步的 …

移动模型
type: item
date: 2025-09-20T22:03:00+08:00
description: 移动模型 RWP（Random Waypoint，随机路标） 空间与时间： 在一个正方形活动区域 $[0,R]\times[0,R]$ 内，离散为 steps 个时间步。 节点运动规则： 初始位置：每个节点在区域内均匀随机选一个起点。 选目标点：从区域内均匀随机再选一个目标点（下一路标）。 速度：对该段路程，从区间 $[v_{\min}, v_{\max}]$ 均匀采样一个速度（以“每步移动的距离”计）。 运动轨迹：用直线匀速插值从当前点走到目标点，按需要的步数填充每个时间步的坐标。 停留：到达目标后，停留 pause_steps ~ U[pause_min, pause_max]（整数步）。 循环：停留结束后再选一个新的随机目标点，重复 3–5。 输出轨迹： 把每个时间步所有节点的 $(x,y)$ 位置拼成矩阵 $Y\in\mathbb{R}^{\text{steps}\times 2N}$。 邻接生成（通讯图）： 对每个时间步，任意两节点距离 $\le$ 通讯半径 comm_radius 则记为一条无向边（1），否则为 0，得到一组对称的 0/1 邻接矩阵序列。 要点：RWP 的目标点在区域内+“可停留”，因此轨迹呈 跳点—直线—驻留的节奏。 RW（Random Walk，随机游走） 空间与时间： 活动区域仍是边长 $R$ 的正方形（或你实现里也支持圆形采样作为初始点）。离散 steps。 节点运动规则： 初始位置：在活动区域内随机取一个点作为起点。 目标点：每次从一个随机边界点或区域内随机点中挑一个当目标（你的实现是 5 种可能：四条边上的均匀点或区域内随机点）。 速度：每段从 $[v_{\min}, v_{\max}]$ 均匀采样一个速度。 运动轨迹：按直线匀速插值走向目标。 无停留：到达目标立即选择下一目标继续走（不驻留）。 循环：重复 2–4。 邻接生成： 与 RWP 相同，以 comm_radius 做阈值逐步形成 0/1 邻接矩阵。 要点：RW 版本不设停留，且目标点常在边界，轨迹更“连续流动”，在边界附近来回穿梭的概率更高。 RD（Random Direction，随机方向） 空间与时间： 同样是正方形区域与离散时间。 节点运动规则： 初始位置：从边界上均匀随机选一个起点（四条边等概率）。 目标点：每段都从边界再均匀随机选一个新的边界点当目标（边界→边界）。 速度：每段速度 $[v_{\min}, v_{\max}]$ 均匀采样。 运动轨迹：直线匀速插值到目标。 停留：到达目标后停留 pause_steps ~ U[pause_min, pause_max] 步。 循环：继续从目标（边界点）出发，选下一个边界点为新目标。 邻接生成： 同上，按 comm_radius 阈值逐步构造邻接矩阵序列。 要点：RD 强化了边界—边界往返与停留，节点会频繁在边缘聚集、驻留，再切换到另一边。 Gaussian Markov Mobility（高斯-马尔科夫移动模型） 空间与时间： 在矩形区域 $[x_{\min}, x_{\max}] \times [y_{\min}, y_{\max}]$ 内，离散为多个时间步。 节点运动规则： 初始状态：每个节点随机生成位置 $(x,y)$，速度 $v \sim U(0.5, v_{\max})$，方向 $\theta \sim U(0,2\pi)$。 速度更新： $v_t = \alpha v_{t-1} + (1-\alpha)\mu_v + \sqrt{1-\alpha^2},\varepsilon_v,$ 其中 $\mu_v$ 是全局平均速度，$\varepsilon_v \sim \mathcal{N}(0,\sigma_v^2)$。 方向更新： $\theta_t = \alpha \theta_{t-1} + (1-\alpha)\mu_\theta + \sqrt{1-\alpha^2},\varepsilon_\theta,$ 其中 $\mu_\theta$ 是平均方向，$\varepsilon_\theta \sim \mathcal{N}(0,\sigma_\theta^2)$。 位置更新： $x_t = x_{t-1} + v_t \cos\theta_t, \quad y_t = y_{t-1} + v_t \sin\theta_t$ 边界处理：若节点越界，则进行反射，即位置镜像回区域内，同时方向在对应维度取反。 循环：重复步骤 2–5，生成连续轨迹。 邻接生成： 同前，设定通信半径 comm_radius，每个时间步任意两节点距离 ≤ 半径则连边，得到动态邻接矩阵序列。 要点： 参数 $\alpha$ 决定轨迹的平滑度/惯性： $\alpha \to 1$：…

K8S
type: item
date: 2025-09-08T21:56:23+08:00
description: 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: 写入期望状态 …

CICD
type: item
date: 2025-09-06T11:28:21+08:00
description: 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 - n…

训练神经网络
type: item
date: 2025-08-31T22:22:27+08:00
description: 🧠 神经网络训练流程基础笔记 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 控制重复多少轮。

草稿
type: item
date: 2025-08-29T09:13:51+08:00
description: 是的，除了 MAE、RMSE 和 MAPE，R²（决定系数，Coefficient of Determination）也是一个常用的评估指标。它用来衡量模型的预测结果与实际数据的拟合度。以下是关于 R² 的详细解释和计算方法。 4. R²（决定系数） 公式： $R^2 = 1 - \frac{\sum_{t=1}^{T} (y_t - \hat{y}t)^2}{\sum{t=1}^{T} (y_t - \bar{y})^2}$ 解释： 分子是误差平方和（Residual Sum of Squares, RSS），表示模型预测值和真实值的偏差。 分母是总平方和（Total Sum of Squares, TSS），表示真实值的偏差。 $\bar{y}$ 是真实值的均值，即 $\bar{y} = \frac{1}{T} \sum_{t=1}^{T} y_t$。 含义： $R^2$ 的值范围 在 [0, 1] 之间，表示模型拟合程度： $R^2 = 1$ 表示完美拟合（模型预测结果与真实值完全一致）。 $R^2 = 0$ 表示模型没有解释任何变异，和用真实值的均值作为预测值一样。 $R^2 < 0$ 表示模型的预测比简单的均值预测还要差。 直观理解： $R^2$ 值越高，模型拟合得越好。 $R^2$ 实际上衡量的是模型解释了数据变异的多少部分。例如，$R^2 = 0.8$ 表示模型解释了 80% 的数据变异。 5. 代码中的实现方式 在你提供的代码中，r2_score 函数是计算 R² 的地方。它是通过以下步骤计算的： r2_score 函数： def r2_score(real, pred): real_mean = np.mean(real) ss_tot = np.sum((real - real_mean) ** 2) # 总变异量 ss_res = np.sum((real - pred) ** 2) # 残差平方和 if ss_tot < 1e-8: return 0.0 return 1 - ss_res / ss_tot 解释： 计算总变异量（TSS）： TSS=∑t=1T(yt−yˉ)2\text{TSS} = \sum_{t=1}^{T} (y_t - \bar{y})^2 其中 $\bar{y}$ 是真实值的均值。 计算残差平方和（RSS）： RSS=∑t=1T(yt−y^t)2\text{RSS} = \sum_{t=1}^{T} (y_t - \hat{y}_t)^2 计算 $R^2$： R2=1−RSSTSSR^2 = 1 - \frac{\text{RSS}}{\text{TSS}} 在代码中，这一过程通过以下两行代码完成： ss_tot = np.sum((real - real_mean) ** 2) ss_res = np.sum((real - pred) ** 2) 然后，最后一步计算出 R² 值： return 1 - ss_res / ss_tot 6. 如何解读 R² 值 R² = 1: 模型完美地拟合了数据，预测值和实际值完全一致。 R² = 0: 模型完全无法拟合数据，与仅用均值预测的效果相同。 R² > 0: 模型的预测比均值预测要好，但可能还存在一些偏差。 R² < 0: 模型的表现比简单的均值模型还差。这意味着模型的预测误差大于仅使用均值作为预测值的误差。 7. R² 的优缺点 优点： 直观：$R^2$ 值介于 0 和 1 之间，便于理解和解释。 标准化：$R^2$ 是标准化的度量，不依赖于数据的量纲。 缺点： 不一定能揭示实际的预测能力：$R^2$ 有时可能会过高，尤其是在过拟合的情况下，即使模型对训练数据表现很好，但对未知数据却不准确。 对异常值敏感：大误差（尤其是异常值）可能会严重影响 $R^2$ 的值。 无法评估模型的偏差：即使 $R^2$ 很高，也不能完全说明模型的预测值和真实值的偏差程度。 8. R² 和其他指标的关系 MAE, RMSE, MAPE 都是直接评估误差的指标，关注的是预测的准确性，而 R² 更多的是评估模型对数据变异的解释能力。 R² 提供了一个模型如何拟合数据的全局视图，而其他指标则给出了更加细化的局部误差信息。 小结 **R²（决定系数）**是评估回归模型拟合程度的重要指标，表示模型预测值与实际值之间的关系程度。它的计算基于总变异量和残差平方和，反映了模型对数据变异的解释能力。 公式： $R^2 = 1 - \frac{\text{RSS}}{\text{TSS}}$ 直观： R² 越接近 1，表示模型对数据的拟合程度越高。 代码： 通过计算残差平方和（RSS）与总变异量（TSS）的比率来得到 R² 值。 这个指标通常与 MAE, RMSE 和 …

RAG知识库
type: item
date: 2025-08-19T22:31:18+08:00
description: Spring AI + Ollama 1. Ollama 定位：本地/容器化的 大模型推理服务引擎 作用：负责加载模型、执行推理、返回结果 支持的模型：Qwen、DeepSeek、nomic-embed-text（embedding 模型）等 交互方式：REST API（默认 http://localhost:11434） ollama run qwen2.5:7b-instruct 2. Spring AI 定位：Spring 官方推出的 AI 接入框架 作用：统一封装对各种 AI 服务的调用逻辑，让开发者更容易接入（OpenAI、Ollama 等） 关键点 OllamaChatModel：封装了调用 Ollama 的对话接口 OllamaOptions：指定模型、参数（温度、上下文大小等） PgVectorStore：对接向量数据库（Spring AI 提供的默认向量数据库适配器。） TokenTextSplitter：默认的文本切分器 （Spring AI 内置逻辑） 3.pgVectorStore pgVectorStore 是 Spring AI 提供的向量存储接口实现，底层基于 PostgreSQL + pgvector 插件。它在项目中的作用： 1）存储向量和元数据： pgVectorStore.accept(splits); 这行代码会： 1.将 splits 中每个 Document 的 text → 调用 embedding 模型 → 生成向量 2.将生成的向量、原始文本、以及文档元数据统一存入数据库表（默认表名：vector_store）； embedding：存储生成的向量； content：存储原始文本内容； metadata：以 JSONB 形式存储元数据。 2）检索时自动生成 SQL： List<Document> documents = pgVectorStore.similaritySearch(request); 在执行检索时，pgVectorStore 会自动生成 SQL 查询， 解析查询请求中的文本； 生成查询向量； 自动构造 SQL（结合 pgvector 的 <-> 向量相似度运算符）； 按相似度排序返回最相关的文档列表。 进一步地，结合 filterExpression（例如 metadata->>'knowledge' = 'xxx'）可在相似度计算的基础上进一步进行条件过滤。 配置 ai: ollama: base-url: http://ollama:11434 #告诉 Spring AI 去 http://ollama:11434 调用模型接口。 embedding: options: num-batch: 512 #批处理参数 model: nomic-embed-text #指定使用的 embedding 模型 rag: embed: nomic-embed-text 注意，需要提前下载模型： ollama pull deepseek-r1:1.5b ollama pull qwen2.5:7b-instruct ollama pull nomic-embed-text ollama list Docker如何开启GPU加速大模型推理 巨坑！ 默认是CPU跑大模型，deepseek1.5b勉强能跑动，但速度很慢，一换qwen2.5:7b模型瞬间就跑不动了，这才发现一直在用CPU跑！！ 如何排查？ 1.查看ollama日志： load_backend: loaded CPU backend from /usr/lib/ollama/libggml-cpu-alderlake.so 2.本地cmd命令行输入，查看显存占用率。 nvidia-smi | 0 NVIDIA GeForce RTX 4060 ... WDDM | 00000000:01:00.0 On | N/A | | N/A 58C P0 24W / 110W | 2261MiB / 8188MiB | 6% Default | 设备状态： RTX 4060显卡驱动（576.02）和CUDA 12.9环境正常 当前GPU利用率仅6%（GPU-Util列） 显存占用2261MB/8188MB（约27.6%） 可见模型推理的时候压根没有用GPU！！！ 解决 参考博客：1-3 Windows Docker Desktop安装与设置docker实现容器GPU加速_windows docker gpu-CSDN博客 1）配置WSL2，打开 PowerShell（以管理员身份运行），执行以下命令： wsl --install -d Ubuntu # 安装 Linux 发行版 wsl --set-default-versi…

拼团设计模式
type: item
date: 2025-08-11T21:40:45+08:00
description: 设计模式 单例模式 懒汉 注意，单例模式的构造函数是私有的！ public class LazySingleton { private static volatile LazySingleton INSTANCE; private LazySingleton() {} public static LazySingleton getInstance() { if (INSTANCE == null) { // 第一次检查 synchronized (LazySingleton.class) { if (INSTANCE == null) { // 第二次检查 INSTANCE = new LazySingleton(); } } } return INSTANCE; } } 第一次检查：防止重复实例化、以及进行synchronized同步块（防止每次加锁的开销）。 第二次检查：防止有多个线程同时通过第一次检查，然后依次进入同步块后，创建N个实例。 volatile：防止指令重排序。 instance = new LazySingleton(); 正确顺序是： memory = allocate(); // 分配内存 ctorInstance(memory); // 调用构造函数，初始化对象 INSTANCE = memory; // 将对象引用赋值给 INSTANCE 由于 JVM 和 CPU 都可能对指令进行优化重排，步骤 ② 和 ③ 的顺序可能被交换！ memory = allocate(); // 分配内存 INSTANCE = memory; // 把引用赋给 INSTANCE（但未初始化完） ctorInstance(memory); // 调用构造函数 线程 A刚执行完赋值（3），但没调用构造函数；此时线程B来了，发现 INSTANCE != null，直接返回这个未初始化完成的对象！！！ 饿汉 public class EagerSingleton { // 类加载时就初始化实例 private static final EagerSingleton INSTANCE = new EagerSingleton(); // 私有构造函数 private EagerSingleton() {} // 全局访问点 public static EagerSingleton getInstance() { return INSTANCE; } } 工厂模式 简单工厂 // 产品接口 interface Product { void use(); } // 具体产品A class ConcreteProductA implements Product { @Override public void use() { System.out.println("使用产品A"); } } // 具体产品B class ConcreteProductB implements Product { @Override public void use() { System.out.println("使用产品B"); } } class SimpleFactory { // 根据参数创建不同的产品 public static Product createProduct(String type) { switch (type) { case "A": return new ConcreteProductA(); case "B": return new ConcreteProductB(); default: throw new IllegalArgumentException("未知产品类型"); } } } public class Client { public static void main(String[] args) { // 通过工厂创建产品 Product productA = SimpleFactory.createProduct("A"); productA.use(); // 输出: 使用产品A Product productB = SimpleFactory.createProduct("B"); productB.use(); // 输出: 使用产品B } } 缺点：添加新产品需要修改工厂类（违反开闭原则） 抽象工厂 抽象工厂模式是一种创建型设计模式，它提供一个接口用于创建相关或依赖对象的家族，而不需要明确指定具体类。 // 抽象产品接口 interface Button { void render(); } interface Checkbox { void render(); } // 具体产品实现 - Window…

测试
type: item
date: 2025-07-31T00:10:03+08:00
description: 测试 小明今天15岁了，它是天水小学上学。