首页
实用链接
图床推荐
友链
关于
Search
1
彻底卸载Cloudflare Tunnel(解决 cloudflared service uninstall 报错问题)
483 阅读
2
从零开始注册Hugging Face账号到部署网页应用
102 阅读
3
Debian 11.2 搭建 Typecho 个人博客教程
90 阅读
4
紫电猫8.8元随身WIFI刷Debian系统教程
88 阅读
5
Linux配置frps与frpc的四种隧道并设置开机启动
87 阅读
默认分类
教程
随笔
软件开发
笔记
登录
/
注册
Search
标签搜索
Datawhale
AI+X
Fun-Transformer
#Datewhale组队学习
隧道
Debian
Transformer
教程
随身wifi
frp
frpc
frps
内网穿透
Linux
toml
我的世界
Minecraft
MySQL
单片机
OLED
Simuoss
累计撰写
20
篇文章
累计收到
12
条评论
首页
栏目
默认分类
教程
随笔
软件开发
笔记
页面
实用链接
图床推荐
友链
关于
搜索到
20
篇与
的结果
2025-09-21
[2025年5月最新] 如何为WSL配置代理 & 如何为Docker配置代理
配置本机WSL代理正常安装好WSL编辑C:\Users\<UserName>.wslconfig,写入以下内容:[wsl2] networkingMode=mirrored localhostForwarding=true autoProxy=true dnsTunneling=true编辑.bashrc,在末尾添加下列隧道配置export http_proxy="http://localhost:10809" export https_proxy="http://localhost:10809"应用更改source ~/.bashrc配置Docker代理正常安装Docker配置 Docker 守护进程 (Docker Daemon) 代理sudo mkdir -p /etc/systemd/system/docker.service.d sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf写入以下内容[Service] Environment="HTTP_PROXY=http://localhost:10809/" Environment="HTTPS_PROXY=http://localhost:10809/"重启Docker服务sudo systemctl daemon-reload sudo systemctl restart docker大功告成!
2025年09月21日
6 阅读
0 评论
0 点赞
2025-09-21
Typecho 1.3.0+ 与 Joe 7.7.1 主题不兼容导致首页文章一直loading的解决方案
前言昨天迁移完博客站就睡了,今早发现博客站换上Joe主题后,首页文章列表竟然无法正常加载,一直显示loading如图:后台和控制台也没有任何报错文章列表无法加载,通常是数据库查询或Widget调用问题。怀疑是Typecho 1.3.0改了一些关键实现,于是开始Debug,发现如下:Typecho 1.3.0 的变化负责处理数据查询、模板渲染等功能的Widget系统经过重构数据库访问层从简单的静态调用升级为更现代的面向对象设计命名空间变化Typecho在1.3.0版本中引入了现代PHP的命名空间机制:旧版本: Typecho_Db::get()新版本: Typecho\Db::get()Widget类体系重构旧版本: Widget_Abstract_Contents新版本: Widget\Base\Contents 或 Widget\Contents\Post\Admin路由系统升级旧版本使用 Typecho_Router::post()新版本的路由注册机制发生了变化解决思路概览了解了问题在哪,就可以着手解决了。处理这个变动,只需要把类似$db = Typecho_Db::get();的语句改为$db = Typecho\Db::get();即可。为了保证前向兼容,可以这样写:/* 兼容Typecho 1.3.0+的数据库类 */ if (class_exists('Typecho\Db')) { $db = Typecho\Db::get(); } else { $db = Typecho_Db::get();修改步骤第一步:修复Widget类继承问题文件:widget.php问题: Joe主题的自定义Widget类继承了旧版本的类名// 原代码 class Widget_Contents_Hot extends Widget_Abstract_Contents修复: 添加版本检测和兼容性处理/* 兼容Typecho 1.3.0+版本检测 */ if (class_exists('Widget\Base\Contents')) { // 新版本基类 class Widget_Contents_Hot extends Widget\Base\Contents { // ... 实现代码 } } else { // 旧版本基类 class Widget_Contents_Hot extends Widget_Abstract_Contents { // ... 实现代码 } }同时修复了数据库排序常量:// 旧版本 ->order('table.contents.created', Typecho_Db::SORT_DESC) // 新版本兼容 ->order('table.contents.created', 'DESC')第二步:修复路由系统文件: core.php问题: 旧版本的路由注册方式在新版本中失效修复: 添加路由系统兼容代码/* 兼容Typecho 1.3.0+的路由系统 */ if (class_exists('Typecho\Router')) { // 新版本路由注册 if (method_exists('Typecho\Router', 'post')) { Typecho\Router::post('/joe/api', 'Joe_Action'); } } else { // 旧版本路由注册 Typecho_Router::post('/joe/api', 'Joe_Action'); }第三步:修复数据库调用修复的文件:functions.phpfunction.phproute.php问题: 所有直接调用 Typecho_Db::get() 的地方都会在新版本中报错修复策略: 在每个数据库调用前添加版本检测/* 兼容Typecho 1.3.0+的数据库类 */ if (class_exists('Typecho\Db')) { $db = Typecho\Db::get(); } else { $db = Typecho_Db::get(); }第四步:添加类别名映射文件: factory.php解决思路: 为了让旧代码能够无缝使用新类名,添加类别名映射:/* 兼容Typecho 1.3.0+的Widget Helper Form类 */ if (class_exists('Typecho\Widget\Helper\Form')) { class_alias('Typecho\Widget\Helper\Form', 'Typecho_Widget_Helper_Form'); } /* 兼容Typecho 1.3.0+的数据库类 */ if (class_exists('Typecho\Db')) { class_alias('Typecho\Db', 'Typecho_Db'); } /* 兼容Typecho 1.3.0+的Widget类 */ if (class_exists('Typecho\Widget')) { class_alias('Typecho\Widget', 'Typecho_Widget'); } /* 兼容Typecho 1.3.0+的Abstract Contents类 */ if (class_exists('Widget\Contents\Post\Admin')) { class_alias('Widget\Contents\Post\Admin', 'Widget_Abstract_Contents'); } elseif (class_exists('Widget\Base\Contents')) { class_alias('Widget\Base\Contents', 'Widget_Abstract_Contents'); }最终能用的版本如果你感觉手动修改有些麻烦,也可以直接使用我改好的版本:Joe7.7.1-typecho1.3.0-fix.zip
2025年09月21日
18 阅读
3 评论
0 点赞
2025-09-21
Typecho博客从本地部署到Docker部署(1.2.1->1.3.0)迁移成功,Congratulations!
前言24年8月,因为Wifi棒子断电重启后无法自动回连Wifi,博客站就迁移到了一块847工控板上。一开始一切运行正常,但到了25年初,工控板经常异常死机,死机时用手摸一下还会自动重启,怀疑是板子电气性能不佳,遂计划把博客站迁移到其他设备上。但是开始迁移时却被一些问题卡住了,届时正值找工作比较忙,于是就先作罢,博客站就此荒废了几个月的时间。这个周末和盒子里的847工控板大眼瞪小眼看了许久,决定把它收拾了,就有了本篇。预先准备我的博客数据库使用SQLite,所以至少应该保留类似66ba4f5eec6c5.db这样的数据库文件。文件的路径通常在typecho\usr下。如果你想保留之前的主题,还需要保留整个typecho\usr\themes文件夹运行博客的新机器上需要先装好docker,为了方便今后的数据迁移,我们使用docker部署使用Docker部署时,建议直接使用docker compose,方便后续维护。compose文件如下:services: typecho: image: joyqi/typecho:nightly-php7.4-apache container_name: typecho-server restart: always environment: - TYPECHO_SITE_URL=https://xxx.xxx ports: - 8634:80 volumes: - ./typecho:/app对比文档里的写法,我们去掉了头部过时的版本声明,修改了宿主机端口,并挂载出了整个/app(也就是Typecho应用程序根目录)。挂载出整个/app的好处有以下两点:如果你的域名使用https,就需要编辑config.inc.php;如果你想迁移主题包,还需要编辑typecho\usr\themes文件夹,那索性就都挂载出来。开始迁移将以上docker compose文件保存到你想放置Typecho的目录,文件名为docker-compose.yaml,然后同级运行命令:docker compose up -d # 如果你不是root,使用sudo docker compose up -d这时docker会从云端仓库把Typecho镜像拉下来,静待一段时间,直到命令行窗口显示:笔者近期家里没有合适的设备,就选择了Windows上使用Docker Desktop部署,之后买了新设备再迁移。在Linux上的回显也大同小异。此时,同目录的typecho文件夹下就是容器内部挂载出的/app目录了。进入typecho\usr,把之前的.db文件(通常类似66ba4f5eec6c5.db)复制过来,然后进入127.0.0.1:8634进行博客初始化。初始界面直接点击我准备好了,开始下一步即可。随后你会看到下面界面,这里按照之前博客的配置选,比如我之前是SQLite,就选SQLite。pdo驱动和原生驱动都可以正常运行,选哪个都行。数据库前缀一般没有人会改,如果你记不清了,可以上类似sqlite-viewer的网站查看,比如我这个db文件夹就是以typecho为前缀的:最下面的数据库文件路径,我们已经把原先的数据库文件放在了正确的地方,所以只要把这里的.db文件的名字改成我们之前名字就好。配置完成点确认开始安装,此时Typecho会提示安装程序检查到原有数据表已经存在,证明我们配对了。选择使用原有数据即可。不出意外的话,会出现如下界面。如果你也到了这里,恭喜你迁移基本成功!可以进入博客界面看看数据都在不在常见问题明明密码正确,但就是登录不进管理界面,点击登录总是被重新定向到登录页,原地tp问题解析:如果站点是通过HTTPS访问的(比如https://blog.simuoss.cn),但Typecho内部没有正确配置为使用安全连接,会导致登录后Session或Cookie处理异常,从而被重定向回登录页。解决方案:在Typecho根目录下的 config.inc.php 文件中,添加以下代码并保存:define('__TYPECHO_SECURE__', true);这行代码告诉Typecho当前环境是安全的(HTTPS),应该生成安全的Cookie。保存后,运行以下指令重启Typecho:docker compose restart # 如果你不是root,使用sudo docker compose restart此时重新登录,就能进管理后台了。进入后台后显示:[升级程序] 检测到新版本!但点升级后报500 SERVER ERROR或DATABASE QUERY ERROR此时先使用以下指令重启:docker compose restart # 如果你不是root,使用sudo docker compose restart如果还是报错,再看下面的解决方案。问题解析:在Docker容器中,Web服务器进程是以特定用户(通常是 www-data)身份运行的,但这个用户不一定有数据库的写入权限,所以升级修改数据库结构时就会失败。解决方案:使用下方命令进入typecho容器内部,并授予www-data用户所有权:docker exec -it typecho-server bash # 进入容器内部命令行。如果你不是root,使用sudo docker exec -it typecho-server bash chown -R www-data /app/usr/ # 将整个目录的所有者设置成`www-data`然后退出容器并重启服务:exit # 退出容器 docker compose restart # 如果你不是root,使用sudo docker compose restart重启后再点击完成升级按钮,即可安全升级到最新版本。如果不重启,直接点升级按钮,还是会报500 SERVER ERROR。这时候不用担心,重启后就可以正常进入管理后台了。如果你在进行这些操作之前已经点过完成升级按钮了,就需要在执行完上述流程之后,先删掉已经损坏的.db文件,重新复制来原先的.db文件,然后使用docker compose restart重启服务,重新进行升级流程。如何迁移主题?前文提到,只要把之前的typecho\usr\themes文件夹复制过来即可。复制来后重启服务,主题就回来了。docker compose restart # 如果你不是root,使用sudo docker compose restart参考链接:Typecho 登录返回 302 的解决方法致谢:阿里Qwen:Debug时帮我提供了很多思路
2025年09月21日
11 阅读
0 评论
0 点赞
2025-01-28
【2025.1 Datawhale AI+X 共学活动】Fun-Transformer —— Task5:项目实践(手写Transformer)
Datewhale组队学习从零实现注意力机制:NumPy 和 SciPy 的实践之旅注意力机制,作为现代深度学习中的核心组件之一,早已在自然语言处理、计算机视觉等领域大放异彩。它的魅力在于能够动态地聚焦于输入数据的关键部分,从而让模型更“聪明”地处理信息。今天,我们将抛开复杂的框架,仅用 NumPy 和 SciPy,从零实现一个通用的注意力机制,深入理解其背后的数学逻辑。1. 词向量:将词汇语义嵌入高维空间一切从词向量开始。词向量是单词在嵌入空间中的数学表示,它将离散的符号转化为连续的向量,从而能够进行数学运算。这里,定义了四个单词的词向量,每个向量的维度为3:import numpy as np from scipy.special import softmax word_1 = np.array([1, 0, 0]) word_2 = np.array([0, 1, 0]) word_3 = np.array([1, 1, 0]) word_4 = np.array([0, 0, 1]) words = np.array([word_1, word_2, word_3, word_4])这些词向量被堆叠成一个矩阵 words,形状为 (4, 3),每一行代表一个单词的嵌入。这一步的意义在于,将离散的符号转化为可计算的数学对象,为后续的注意力计算奠定基础。2. 权重矩阵:映射到查询、键和值注意力机制的核心在于查询(Query)、键(Key)和值(Value)的生成。这些概念听起来抽象,但本质上是将词向量映射到不同的空间中,以便计算它们之间的关系。通过随机初始化三个权重矩阵 W_Q、W_K 和 W_V,词向量被转换为查询、键和值:np.random.seed(42) W_Q = np.random.randint(3, size=(3, 3)) W_K = np.random.randint(3, size=(3, 3)) W_V = np.random.randint(3, size=(3, 3)) Q = words @ W_Q K = words @ W_K V = words @ W_V查询、键和值的生成过程,本质上是矩阵乘法。这一步的意义在于,将原始的词向量映射到不同的语义空间中,为后续的相似度计算做准备。3. 得分计算:量化相似度接下来,通过查询和键的点积,计算得分矩阵。每个得分表示一个查询向量与一个键向量的相似度:scores = Q @ K.T得分的计算是注意力机制的关键步骤之一。点积越大,表示两个向量越相似。这一步的意义在于,量化每个查询向量与所有键向量之间的关系,为后续的权重分配提供依据。4. 权重分配:Softmax 概率化得分矩阵虽然量化了相似度,但还需要将其转化为概率分布。这里,softmax 函数登场了。通过对得分进行缩放并应用 softmax,得到了注意力权重:weights = softmax(scores / np.sqrt(K.shape[1]), axis=1)softmax 的作用是将得分转化为概率分布,使得每个查询向量对所有键向量的权重之和为1。缩放操作则是为了保持数值稳定性,防止得分过大或过小导致计算溢出或下溢。5. 注意力输出:加权求和最后,通过加权求和的方式,计算注意力输出。每个注意力输出是所有值向量的加权和,权重由 softmax 函数计算得到:attention = weights @ V print(attention)注意力输出的计算是注意力机制的最终步骤。通过加权求和,模型能够动态地聚焦于输入序列中最相关的部分,从而生成更准确的输出。多头注意力机制:从单头到多头的进化注意力机制的核心思想是让模型能够动态地关注输入序列中的不同部分,从而更好地捕捉上下文信息。然而,单头注意力机制有一个明显的局限性:它只能从一个角度捕捉输入序列的信息。为了克服这一限制,多头注意力机制(Multi-Head Attention)应运而生。通过并行地计算多个注意力头,模型能够从不同的子空间中提取信息,从而更全面地理解输入数据。今天,我们将深入探讨多头注意力机制的实现,并通过 PyTorch 实现一个完整的 MultiHeadAttention 类。1. 多头注意力机制的核心思想多头注意力机制的核心在于将输入数据映射到多个子空间中,并在每个子空间中独立地计算注意力。具体来说,输入数据会被线性变换为多个查询(Query)、键(Key)和值(Value),然后在每个头上分别计算注意力。最后,所有头的输出会被拼接起来,并通过一个线性层映射回原始维度。这种设计的好处在于:多视角捕捉信息:每个头可以关注输入序列的不同部分,从而捕捉更丰富的特征。并行计算:多个头的计算可以并行进行,提高了计算效率。灵活性:通过调整头的数量,可以控制模型的复杂度和表达能力。2. 实现细节:从代码中理解多头注意力以下是一个完整的 MultiHeadAttention 类的实现,我们将逐行解析其关键部分。import math import torch import torch.nn as nn import torch.nn.functional as F class MultiHeadAttention(nn.Module): def __init__(self, heads, d_model, dropout=0.1): super().__init__() self.d_model = d_model # 模型的总维度 self.d_k = d_model // heads # 每个头的维度 self.h = heads # 头的数量 # 线性层,用于生成 Q、K、V self.q_linear = nn.Linear(d_model, d_model) self.k_linear = nn.Linear(d_model, d_model) self.v_linear = nn.Linear(d_model, d_model) # Dropout 层,用于正则化 self.dropout = nn.Dropout(dropout) # 输出线性层,用于将多头输出映射回模型维度 self.out = nn.Linear(d_model, d_model) def attention(self, q, k, v, mask=None): # 计算 Q 和 K 的点积,并除以 sqrt(d_k) 进行缩放 scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.d_k) # 如果提供了掩码,则将掩码对应的位置设置为负无穷 if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) # 应用 softmax 计算注意力权重 scores = F.softmax(scores, dim=-1) # 应用 dropout scores = self.dropout(scores) # 将注意力权重与 V 相乘,得到输出 output = torch.matmul(scores, v) return output def forward(self, q, k, v, mask=None): batch_size = q.size(0) # 将输入通过线性层,并调整形状以进行多头计算 q = self.q_linear(q).view(batch_size, -1, self.h, self.d_k).transpose(1, 2) k = self.k_linear(k).view(batch_size, -1, self.h, self.d_k).transpose(1, 2) v = self.v_linear(v).view(batch_size, -1, self.h, self.d_k).transpose(1, 2) # 计算注意力输出 scores = self.attention(q, k, v, mask) # 将多头输出拼接,并调整形状以匹配模型维度 concat = scores.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model) # 通过输出线性层 output = self.out(concat) return output3. 关键步骤解析1. 初始化参数d_model:模型的总维度。d_k:每个头的维度,等于 d_model // heads。heads:头的数量。线性层 q_linear、k_linear、v_linear:用于将输入映射到查询、键和值。out:输出线性层,用于将多头输出映射回模型维度。2. 注意力计算点积计算:通过矩阵乘法计算查询和键的点积,并除以 sqrt(d_k) 进行缩放,以防止点积过大。掩码处理:如果提供了掩码,则将掩码对应的位置设置为负无穷,这样在 softmax 后这些位置的值为0。Softmax:将得分转换为概率分布。Dropout:对注意力权重进行随机丢弃,防止过拟合。加权求和:将注意力权重与值相乘,得到输出。3. 前向传播线性变换:将输入通过线性层,生成查询、键和值。形状调整:将输入调整为 (batch_size, heads, seq_len, d_k),以便进行多头计算。注意力计算:在每个头上独立计算注意力。拼接输出:将所有头的输出拼接起来,并通过输出线性层映射回模型维度。4. 测试与验证以下代码用于测试 MultiHeadAttention 类的功能:if __name__ == "__main__": heads = 4 d_model = 128 # d_model 必须是 heads 的整数倍 dropout = 0.1 model = MultiHeadAttention(heads, d_model, dropout) batch_size = 2 seq_len = 5 q = torch.rand(batch_size, seq_len, d_model) # Query k = torch.rand(batch_size, seq_len, d_model) # Key v = torch.rand(batch_size, seq_len, d_model) # Value output = model(q, k, v) print("Output shape:", output.shape) # 应该是 [batch_size, seq_len, d_model] loss = output.mean() loss.backward() print("Backward pass completed.")输出结果:Output shape: torch.Size([2, 5, 128]) Backward pass completed.欢迎各位大佬在评论区交流&批评指正!Datewhale组队学习参考链接Datawhale AI+X 共学活动 Fun-Transformer —— Task5:项目实践Attention Is All You Need
2025年01月28日
7 阅读
0 评论
0 点赞
2025-01-25
【2025.1 Datawhale AI+X 共学活动】Fun-Transformer —— Task4:Decoder
Datewhale组队学习*即将到来欢迎各位大佬在评论区交流&批评指正!Datewhale组队学习参考链接Datawhale AI+X 共学活动 Fun-Transformer —— Task4:DecoderAttention Is All You Need
2025年01月25日
5 阅读
0 评论
0 点赞
1
2
...
4