0%

我业余在做一个 A 股量化分析系统:自动拉数据、算因子、做因果推断、生成个股分析报告。它从最初十几个互相调用的脚本,长成了一个有数据层、因子层、模型层、决策层、复盘层的系统。这篇是写给”想做量化系统、但还停在写脚本阶段”的新手的复盘——不讲怎么调参赚钱,只讲怎么把系统的骨架搭对。 因为我越做越确信:量化里真正难的不是策略,是工程。

Read more »


这是一篇写给自己的复盘。我是个写了多年 Python / JS 的程序员,业余时间用 Godot 做一款像素风的「连线消除 + Roguelike」单机游戏(暂名《勇闯昆图库塔》)。从一张白纸到一个能让真人坐下来玩的版本,踩了不少坑,也总结出一些”早知道就好了”的经验。趁记忆还热,记下来温故知新。

Read more »


Supabase作为开源的后端即服务(BaaS)平台,支持开发者快速构建应用,同时提供灵活的自建部署选项。

alt text

alt text

本文将基于官方Docker部署教程,结合实践经验,详细说明自部署流程与注意事项。

环境准备

  • 安装Docker与Docker Compose
    确保系统已安装Docker及Docker Compose工具。
1
2
docker --version
docker compose version
  • 生成安全密钥
    访问Supabase密钥生成页面,生成以下密钥并保存至安全位置:

    • JWT_SECRET
    • ANON_KEY
    • SERVICE_ROLE_KEY
  • 部署步骤

    • 克隆Supabase代码库
    1
    2
    git clone --depth 1 https://github.com/supabase/supabase
    cd supabase/docker
    • 配置环境变量
      复制示例配置文件并编辑, 将生成安全密钥步骤下生成的密钥,copy到.env文件中对应的位置。
    1
    2
    cp .env.example .env
    vi .env
    • 拉取Docker镜像
      这里推荐墙内镜像地址:dytt.online
    1
    docker compose pull
    • ​启动Supabase服务
    1
    docker compose up -d

    服务启动后,通过docker compose ps检查容器状态,确认所有服务正常运行。

    1
    docker ps
    • ​访问管理界面
      • ​Studio:http://localhost:8000(默认账号:supabase,密码见.env文件)
      • Logflare界面: http://localhost:4000

核心服务

服务名称 功能描述 访问端口
supabase-db PostgreSQL数据库 5432
supabase-auth 用户身份认证 3000
supabase-studio 管理控制台 8000
supabase-analytics Logflare控制台 4000

关闭与卸载

  • 停止服务
1
docker compose down
  • 彻底清理
1
2
docker system prune -a
rm -rf .supabase

一些常见问题

  • 1
    2
    3
    4
    5
      * 必须32位,而不是*32-chars-min*
    * 已提交[issus](https://github.com/supabase/supabase/pull/34171)
    * 如果```supabase-analytics```服务一直在重启,则查看容器日志。
    ```bash
    docker logs --details supabase-analytics
    若提示数据库账号密码验证失败,则需要进入supabase-db容器,给每个pgSQL账号设置密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker exec -it supabase-db /bin/bash

# 进入容器后
psql -U postgres -W
# 输入默认密码,比如:postgres
# 进入后查看用户列表
SELECT rolname,rolpassword FROM pg_authid;

# 修改用户密码
ALTER USER supabase_admin WITH PASSWORD 'postgres';
ALTER USER supabase_auth_admin WITH PASSWORD 'postgres';
ALTER USER supabase_storage_admin WITH PASSWORD 'postgres';
...

修改完成后重启容器, 然后访问http://localhost:8000

1
2
3
docker compose down
docker compose up -d

资料参考

  • 官方教程: Self-Hosting with Docker
  • 74.1k!Star分分钟搭建百万用户在线系统?Supabase 帮你轻松实现!
  • 如何使用Docker配置和部署Supabase


  • 重置&清理 docker容器和镜像
1
2
3
4
5
6
7
8
9
10
11
12

# 删除所有容器
docker compose down

# 重启
docker compose restart

# 真男人😂
docker system prune -a
sudo rm -rf docker/volumes/db/data
docker compose up


在使用 UniVpn 进行 SSL VPN 连接时,为了确保网络连接的稳定性和可靠性,您可能需要启用自动重连功能。该功能可以在 VPN 连接意外中断时自动重新建立连接,从而减少因网络中断带来的不便。本文将介绍如何在 Linux 操作系统下,通过结合 expect 脚本和 ping 探测来实现自动重连功能。

环境准备

以 UniVpn 为例,我们将通过以下步骤实现自动重连:

启动 VPN 客户端

首先,在 shell 命令行中运行以下命令来启动 UniVpn,并创建一个 VPN 连接:

1
/usr/local/UniVPN/serviceclient/UniVPNCS

编写 expect 脚本

由于需要自动处理 VPN 连接,您需要安装 expect 程序。该工具能够自动化与命令行交互的操作。

安装 expect

1
apt install expect

然后,编写一个 expect 脚本(例如 univpn_run.sh),用于监控并自动重连 VPN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
while true
do
expect <<EOF
set timeout -1
spawn /usr/local/UniVPN/serviceclient/UniVPNCS

# 等待欢迎信息
expect "Welcome to UniVPN"
send "3\r"

# 等待连接选项
expect "*1:Connect*"
send "1\r"

# 等待连接成功提示
expect "*Please input the login user name*"
send "[username]\r" #这里输入vpn用户名

# 等待输入密码提示
expect "*Please input the login user password*"
send "[password]\r" #这里输入vpn密码

# 等待最终连接成功提示
expect "*Connect Success,Enjoy*"

spawn sh ./testping.sh #这里是一个探测ping的代码
expect "*IP testing error*"

send "q\n"
expect "*Logout succeeded.*"

EOF

sleep 2
done

编写 ping 探测脚本

接下来,编写一个用于检测网络连通性的 ping 脚本(例如 testping.sh)。该脚本会定期检测 VPN 连接是否正常,若检测到连接中断,则会触发自动重连。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
while true
do
# 要ping的IP地址
IP_ADDRESS="xxx.xxx.xxx.xxx" #vpn连接上以后能ping通的一个ip

# 执行ping命令,检查IP地址是否可达
ping -c 1 $IP_ADDRESS > /dev/null 2>&1

# 检查ping命令的退出状态
if [ $? -eq 0 ]; then
echo "IP testing success" #如果ping通了,输出
else
echo "IP testing error" #如果ping不通了,输出
exit
fi
sleep 20 #每20秒ping一次
done

执行自动重连

最后,执行以下命令运行自动重连脚本:

1
2
chmod +x univpn_run.sh testping.sh &  ./univpn_run.sh

该脚本将持续检测网络状态,若 ping 不通,则会结束当前 VPN 连接并尝试重新连接。

注意事项

在多次连接后,可能会出现 VPN 无法正常连接的情况,这通常是由于网卡问题导致的。为解决这一问题,您可以编写一个脚本,在探测到网络故障后,自动重启网络服务。

此外,若重启网络服务后某些依赖网络的服务(如 Docker)出现问题,您可以在脚本中加入这些服务的重启命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash

# crontab设置: 30分钟执行一次检查
# */30 * * * * /root/dashboard/v2-web/docs/network_check.sh

# 目标IP地址
TARGET_IP="127.0.0.1" #这里换成你的IP地址

# 使用ping命令连续ping指定次数(例如每10秒一次,共ping 3次)
COUNT=1 #这里探测多少次
INTERVAL=10 #这是每次探测的间隔时间

# 使用ping命令进行测试
RESULT=$(ping -c $COUNT -i $INTERVAL $TARGET_IP | grep 'Destination Host Unreachable')

# 如果ping的结果包含"Destination Host Unreachable"
if [[ "$RESULT" != "" ]]; then
echo "$(date) - Ping to $TARGET_IP failed. Restarting network service..."

# 使用systemctl命令重启网络服务
systemctl restart network
#systemctl restart docker #这里是因为重启了network以后,docker的网络会出现问题,所以就重启一下docker。如果你有其他服务也可以这样重启一下。

fi
exit 0

定时检测

为了确保 VPN 的稳定性,您可以将上述脚本与定时任务(如 cron)结合,定期执行 ping 探测,确保在网络异常时及时恢复连接。


通过上述步骤,您可以在 Linux 操作系统下实现 UniVpn 的自动重连功能,从而提升网络连接的稳定性和可靠性。


CNN 是什么?

在机器学习中,分类器将类标签分配给数据点。例如,图像分类器为图像中存在的对象产生一个类标签(例如鸟、飞机)。卷积神经网络(CNN)是一种类型的分类器,擅长解决这个问题!

CNN是一种神经网络:用于识别数据中的模式的算法。神经网络通常由一组神经元组成,这些神经元组织成层,每层都有自己可学习的权重和偏差。让我们将CNN分解为多个基本构建模块。

  1. 一个张量可以被视为一个n维矩阵。在上述CNN中,张量将是三维的,除了输出层。
  2. 一个神经元可以被视为一个接受多个输入并产生单个输出的函数。神经元的输出在上面被表示为红色→蓝色的激活图。
    一个层简单地是具有相同操作的神经元的集合,包括相同的超参数。
  3. 一个层简单地是具有相同操作的神经元的集合,包括相同的超参数。
  4. 核权重和偏差,虽然对每个神经元都是独特的,但在训练阶段进行调整,并且允许分类器适应所提供的问题和数据集。它们在可视化中使用黄色→绿色的差异颜色刻度进行编码。具体的值可以通过点击神经元或悬停在卷积弹性解释视图中的核/偏差上来查看交互式公式视图中的。
  5. CNN表达了一个可微分的评分函数,这在输出层的可视化中表示为类别得分。

如果您之前学习过神经网络,这些术语可能听起来很熟悉。那么CNN有何不同之处呢?CNN利用一种特殊类型的层,恰当地称为卷积层,使它们能够很好地学习图像和类似图像的数据。关于图像数据,CNN可用于许多不同的计算机视觉任务,如图像处理、分类、分割和目标检测。

在CNN Explainer中,您可以看到一个简单的CNN如何用于图像分类。由于网络的简单性,其性能并不完美,但这没关系!CNN Explainer中使用的网络架构Tiny VGG包含了如今最先进的CNN中使用的许多相同层和操作,但规模较小。这样,入门将会更容易理解。

每个网络层都有什么作用?

让我们逐层了解网络中的每一层。在阅读时,可以随意与可视化工具-CNN Explainer进行交互,点击和悬停在不同部分。

输入层(Input Layer)

输入层(最左边的层)代表CNN中的输入图像。因为我们使用RGB图像作为输入,输入层有三个通道,分别对应红色、绿色和蓝色通道,在这个层中显示。当您点击上面的网络详情图标时,使用颜色标尺显示详细信息(在这一层和其他层上)。

卷积层(Convolutional Layers)

卷积层是CNN的基础,因为它们包含了学习到的卷积核(权重),这些卷积核可以提取出区分不同图像的特征,这正是我们进行分类所需要的!当您与卷积层交互时,您会注意到前一层和卷积层之间的联系。每个连接代表一个独特的卷积核,用于卷积操作以生成当前卷积神经元的输出或激活图。

卷积神经元执行一个逐元素的点积运算,使用一个独特的卷积核和前一层对应的神经元的输出。这将产生与独特卷积核数量相同的中间结果。卷积神经元是所有中间结果与学习到的偏置求和的结果。

例如,让我们看一下上面Tiny VGG架构中的第一个卷积层。注意这一层有10个神经元,但前一层只有3个神经元。在Tiny VGG架构中,卷积层是全连接的,意味着每个神经元与前一层的每个神经元都有连接。关注第一个卷积层中最上面的卷积神经元的输出,当我们悬停在激活图上时,我们可以看到有3个独特的卷积核。


Figure 1. As you hover over the activation map of the topmost node from the first convolutional layer, you can see that 3 kernels were applied to yield this activation map. After clicking this activation map, you can see the convolution operation occuring with each unique kernel.

这些核的大小是由网络架构的设计者指定的超参数。为了产生卷积神经元(激活图)的输出,我们必须对上一层的输出和网络学习的唯一核进行逐元素点积运算。在TinyVGG中,点积运算使用1的步幅,这意味着每个点积中核都会移动1个像素,但这是网络架构设计者可以调整以更好地适应其数据集的超参数。我们必须对所有3个核执行此操作,这将产生3个中间结果。


Figure 2. The kernel being applied to yield the topmost intermediate result for the discussed activation map.

然后,执行元素级求和,其中包含所有3个中间结果以及网络学习的偏差。之后,生成的二维张量将是在上述界面中查看的第一个卷积层中最顶层神经元的激活图。必须应用相同的操作来生成每个神经元的激活图。

通过一些简单的数学运算,我们可以推断出在第一个卷积层中有3 x 10 = 30个独特的大小为3x3的卷积核。卷积层与前一层之间的连接是在构建网络架构时的设计决策,这将影响每个卷积层中的卷积核数量。

了解超参数(Hyperparameters)

Hyperparameters

  1. 填充(Padding) 通常在卷积核超出激活图时是必要的。填充可以保护激活图边缘的数据,提高性能,并有助于保持输入的空间大小,使架构设计师能够构建更深、性能更高的网络。存在许多填充技术,但最常用的方法是零填充,因为它具有性能好、简单和计算效率高的特点。该技术涉及在输入的边缘对称地添加零。这种方法被许多高性能的CNN(卷积神经网络)如AlexNet所采用。

  2. 卷积核大小(Kernel size) ,通常也称为滤波器大小,指的是在输入上滑动窗口的尺寸。选择这个超参数对图像分类任务有巨大影响。例如,小卷积核尺寸能够从输入中提取包含高度局部特征的大量信息。正如您在上面的可视化中所看到的,较小的卷积核尺寸还导致层维度的减小,从而允许更深的架构。相反,大卷积核尺寸提取较少信息,导致层维度更快地减小,通常导致性能更差。大卷积核更适合提取较大的特征。最终,选择适当的卷积核大小将取决于您的任务和数据集,但一般来说,较小的卷积核大小能够提高图像分类任务的性能,因为架构设计者能够将更多层叠加在一起,以学习更复杂的特征!

  3. 步幅(Stride) 表示卷积核每次应移动多少像素。例如,如上所述的卷积层示例中,Tiny VGG在其卷积层中使用步幅1,这意味着对输入的3x3窗口执行点积以产生输出值,然后每次后续操作都向右移动一个像素。步幅对CNN的影响类似于卷积核大小。随着步幅减小,学到的特征更多,因为提取更多数据,这也导致更大的输出层。相反,随着步幅增加,这导致特征提取受限,并且输出层尺寸更小。架构设计者的责任之一是确保在实现CNN时卷积核对输入进行对称滑动。使用上面的超参数可视化来改变各种输入/卷积核维度上的步幅,以理解这个约束!

激活函数(Activation Functions)

ReLU

神经网络在现代技术中非常普遍——因为它们非常准确!如今性能最高的CNN由大量层组成,能够学习更多特征。这些开创性的CNN能够实现如此巨大的准确性,部分原因是它们的非线性特性。ReLU将非线性引入模型中,这是非常必要的。非线性对于产生非线性决策边界是必要的,这样输出就不能被写成输入的线性组合。如果没有非线性激活函数,深度CNN架构将退化为一个等效的卷积层,性能远不如现在。ReLU激活函数被专门用作非线性激活函数,而不是其他非线性函数,比如Sigmoid,因为经验观察表明使用ReLU的CNN训练速度更快。

ReLU 激活函数是一种one-to-one的数学运算:

Figure 3. The ReLU activation function graphed, which disregards all negative data.

该激活函数是对输入张量中的每个值逐元素应用的。例如,如果在值2.24上应用ReLU,则结果将是2.24,因为2.24大于0。您可以通过点击上面网络中的ReLU神经元来观察此激活函数的应用。在上述网络架构中的每个卷积层之后执行修正线性激活函数(ReLU)。注意此层对网络中各个神经元的激活图的影响!

Softmax

Softmax

一个softmax操作起到了关键作用:确保CNN的输出总和为1。因此,softmax操作对于将模型输出缩放为概率非常有用。单击最后一层可以看到网络中的softmax操作。注意,展开后的logits没有在0到1之间进行缩放。为了直观地显示每个logit(未缩放的标量值)的影响,它们使用浅橙色到深橙色的颜色比例进行编码。经过softmax函数处理后,每个类现在对应适当的概率!

也许你会想到标准归一化和softmax之间的区别——毕竟,它们都将logits重新缩放到0到1之间。请记住,反向传播是训练神经网络的关键方面——我们希望正确答案具有最大的“信号”。通过使用softmax,我们实际上是在“近似”argmax,同时获得了可微性。重新缩放不会使最大值比其他logits显著地更高,而softmax会。简而言之,softmax是一个“更柔和”的argmax。

Figure 4. The Softmax Interactive Formula View allows a user to interact with both the color encoded logits and formula to understand how the prediction scores after the flatten layer are normalized to yield classification scores.

池化层(Pooling Layers)

不同的CNN架构中有许多种类型的池化层,但它们都旨在逐渐减少网络的空间范围,从而减少网络的参数和整体计算。上面的Tiny VGG架构中使用的池化类型是最大池化。

最大池化操作在架构设计过程中需要选择核大小和步幅长度。一旦选择了,该操作会在输入上滑动指定步幅的核,而仅选择每个核切片中的最大值,以产生输出的值。可以通过点击上面网络中的池化神经元来查看该过程。

在上述的Tiny VGG架构中,池化层使用2x2的核和步幅为2。这种具体规格的操作导致了75%的激活被丢弃。通过丢弃这么多数值,Tiny VGG更具计算效率,并避免过拟合。

展平层(Flatten Layer)

该层将网络中的三维层转换为一维向量,以适应用于分类的全连接层的输入。例如,一个5x5x2张量将被转换为大小为50的向量。网络的先前卷积层从输入图像中提取特征,但现在是对这些特征进行分类的时候了。我们使用softmax函数对这些特征进行分类,这需要一个一维输入。这就是为什么需要展平层。可以通过单击任何输出类来查看这一层。

资料来源

  • https://poloclub.github.io/cnn-explainer/
  • 视频教学