我需要一个概率论词汇中英对照表。事情的起因,是为了帮助我一位需要参加北大光华夏令营笔试的好朋友。因为笔试只考概率论,但是题目很有可能是英文的。夏令营通知给的参考文献是 DeGroot, M. H. & Schervish, M. J. (2012). Probability and statistics (fourth edition),这本书只有第三版有中文版。书后面有个 Index,给出了这本书里比较重要的名词、概念和人名,以及其对应的参考页码。这个 Index 有一千多词,我第一个想法是使用 ChatGPT 的 API 把它们翻译一遍。

我找到了 pdf 电子版并复制了 Index,然后用正则表达式修复了一下格式和复制错误等问题,把它弄成了纯文本形式。给点例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Allison, D. B., 400
Alternative hypothesis, 531
Anagnostopoulos, P., xii
Analysis of variance, 754
one-way layout, 755
residuals, 760
two-way layout, 763
with replications, 773
...
Bergin, P., xii
Bernoulli distribution, 97, 276
conjugate prior for, 394-395
m.g.f., 276
...

接下来就是按行处理。Index 给出的一些概念是有层级关系的,用缩进表示。那么按行处理文本的时候弄一个栈存一下当前词的上下文即可。所有的概念全名就是把它和先前层次的名词都连起来,虽然会有点语序问题。处理完了可以得到结构化的数据 data,是一个全名为 key 的字典。

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
import re

data = {}

term_stack = []
for line in lines:
depth = 0
while (line.startswith(" ")):
depth += 1
line = line[4:]

simp_name = re.sub(r",\s*([-\d]+|[-ivx]+)", "", line).strip()
page_matches = re.findall(r"\b([-\d]+|[-ivx]+)\b", line)
page_refs = [page for page in page_matches] if page_matches else []

full_name = " ".join(term_stack[:depth] + [simp_name])
del term_stack[depth:]
term_stack.append(simp_name)

entry = {
"suffix name": simp_name,
"pages": page_refs,
}

data[full_name] = entry

这里拿 \b([-\d]+|[-ivx]+)\b 来匹配页码和页码范围,但是有可能匹配到正文中的连字符 - 可以寻思着改进一下。

结构化的数据有了接下来是重头戏,拿 ChatGPT 翻译这些概念。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import openai

openai.api_key = "YOUR KEY HERE"

def translate_term(term):
global usage
prompt = "Give the corresponding Simplified Chinese term given by the user. The term must be in the area of Probability and Statistics. You should only give one word or phrase without any other supplementary text or Pinyin."

for _ in range(10):
try:
completion = openai.ChatCompletion.create(
model = "gpt-3.5-turbo",
messages = [{"role": "system", "content": prompt},
{"role": "user", "content" : term}]
)
except Exception:
print("Completion failed, retrying...")
continue
break

usage += completion.usage.total_tokens
return completion.choices[0].message.content.strip()

直接使用 OpenAI 的 Python 库。我本来是问了一下 ChatGPT 怎么用 API,但是 ChatGPT 只会用 text-davinci completion 模型,并不知晓 gpt-3.5-turbo 模型的存在。所以还是看了一眼官方文档。这个 openai.ChatCompletion.create API 是会抛异常的,包括网络不通、API 额度超限、服务器过载等等问题,所以需要简单实现个重试机制。

这个脚本花了快一个小时才跑完 1000 余个概念,基本是在等 API response,而且十几个 request 就得有一次超负荷或者断连得重试。跑出来的结果也一般。我都明确告诉它了不要附汉语拼音它有时候还是要加上。也有不少人名它不认识并告诉我这不是概率统计的内容所以拒不翻译,这个倒不怪它。下面是一些奇葩回应大赏。

阅读全文 »

近日将博客使用的 Next 主题从好久不更新的 Github 仓库 部署方式切到了 npm,也获得了版本的升级。并且我现在把博客在 Railway 上以 Docker 加 Nginx 的方式托管,不再用 Github Pages 了。

原来的用的好好的,为什么要多此一举呢?本质原因可能是因为我要整理一下目前正在用的域名,打算以后都使用 junyang.me 这个域名。但是原先的 jyzhang.xyz 因为也分享给了别人,所以要保持很长一段时间的可用。Github Pages 并不能使用多个自定义域名,于是想要搬迁。还有一个次要原因,可能是因为我最近玩 OpenAI API,搭了个 GPT-3.5-turbo 的镜像站给家人用,用 Railway 部署了 ChatGPT WEB,感觉 Railway 很好用,于是购买了 plan。心想买都买了就把博客搞过来吧。

为 Hexo 编写 Dockerfile

Hexo 生成的是静态网站,如果不想在静态页面托管处使用,可以搭建 Nginx 服务器。Railway 上的话就用 Docker 部署 Nginx 即可(实际上也不支持别的方式)。我直接在 Hexo 的博客仓库里加了个 Dockerfile,这样每次 Github commit 之后就会自动触发构建,更新到网站上。

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
38
39
40
41
42
43
44
45
# first stage: build the site using node
FROM node:latest

MAINTAINER junyangzhang, user@junyang.me

# install hexo and others in package.json
WORKDIR /root/src
COPY . /root/src
RUN npm install hexo-cli -g && npm install

# install pandoc
# get package based on architecture
RUN ARCH=$(dpkg --print-architecture) \
&& echo "Architecture: $ARCH" \
&& if [ "$ARCH" = "amd64" ]; then \
wget https://github.com/jgm/pandoc/releases/download/3.1.1/pandoc-3.1.1-1-amd64.deb && \
dpkg -i pandoc-3.1.1-1-amd64.deb; \
elif [ "$ARCH" = "arm64" ]; then \
wget https://github.com/jgm/pandoc/releases/download/3.1.1/pandoc-3.1.1-1-arm64.deb && \
dpkg -i pandoc-3.1.1-1-arm64.deb; \
else \
echo "Unsupported architecture: $ARCH"; \
exit 1; \
fi

# make inplace style changes
RUN chmod +x customization/alter_styles.sh && ./customization/alter_styles.sh

# build the site
RUN hexo generate

# second stage: configure nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/hexosite.conf
RUN mkdir -p /var/logs/ && touch /var/logs/error.log && touch /var/logs/nginx.pid

# get the built site from the node stage
RUN mkdir -p /usr/share/nginx/html/public
COPY --from=0 /root/src/public /usr/share/nginx/html/public

# hexo default port
EXPOSE 4000

# run hexo server
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

这个 Dockerfile 有两个 Stage,思路就是先用 Node.js 镜像构建网站,然后再配置 Nginx 镜像并把上一个阶段的静态网站输出拷贝到 Nginx 镜像来。我之前也写过同一个 Stage 的方案,后来发现服务端并不需要 Node.js,分成两个阶段的话第一个阶段的文件都不会出现在最终镜像里,实际部署的大小不到一百兆。如果包含 Node.js,就有一个多 G 了。

第一阶段

第一个阶段,先在 node 镜像上拷贝所有网站源码,并安装 Hexo。npm install 指令会按照源码中的 package.json 安装需要的模块。另外,Hexo 构建的时候需要安装非 npm 模块 pandoc,所以第一个阶段需要下载 pandoc 安装。我本地是 M1 Mac,云端是 x86,为了本地能构建,所以增加了不少判断指令集的代码。

第一个阶段在真正构建静态网站之前,我添加了修改主题的一个脚本 ./customization/alter_styles.sh,来完成外置 .styl 文件没法做到的事情,这个干了什么就后面再说吧。

第二阶段

阅读全文 »

由于需要做操作系统的工作,但是只上了比较没用的西交理论课,于是我不会 OS 开发(暂时)。组里推荐了清华课用的 rCoreOS,于是自学并尝试做一些作业。

主要跟着 rCoreOS Tutorial 的在线书学习,如果有一定 CS 理论知识基础和 Rust 基础,学起来应该很轻松。如果会用 C 做内核开发但是不会 Rust,这本书也是不错的 Rust 内核(从零)开发的教程。还有就是,本书跟 Linux 没什么关系,不需要很会。

Repo: rCore-Tutorial-v3

Book: rCore-Tutorial-Book-v3

在线书已经写的比较新手友好了,参考答案也存在,但是不全,并且实验也有一些不大的坑,或者书和代码有出入。我觉得写这篇文章可以帮助你更快搞定一些没详细写到的内容,于是分享此笔记。先看书,要做实验的时候可以看看这个。

我在 2023 年二月份进行的学习,目前这个课程的材料仍在不断更新,所以以下内容也仅供参考。

第零章

第零章如果理论学过了大可不细看,仅搭环境即可。

我用的老师的 x86 Ubuntu 服务器。VSCode SSH 连接 Remote 开发。编译运行的时候直接用 Docker 环境,省去很多麻烦。本地也可以复用这套环境。Clone 仓库后进入目录即可 Make Docker 镜像。

这个 Docker 镜像包括了运行需要的 QEMU 7.x.x,编译需要的 Rust 和 C 工具链。课程的框架代码不在镜像里。镜像里面也没有 RISCV GDB,所以需要自行下载,并修改一下 Dockerfile 加入 GDB,再构建。

阅读全文 »

去年有人反应我的博客公式炸了,我看了看是因为 jsdelivr 炸了,我觉得总会好的,就没管。没想到 2023 年了,jsdelivr 还是炸的。查了查,看到是因为它在大陆的 ICP 认证到期了。现在不得不修了。

NetworkDebug

简略讲一讲原理。我的博客渲染公式用了 MathJax,这是一个浏览器上运行的 Javascript 库。自然,作为库,可以不用在博客服务器上存着,而是需要的时候从别的地方得到。这样大家的网站就可以共享实时更新的库,节省各自的服务器空间和流量了。

那 MathJax 从哪来呢,一般是由博客网站指定一个提供者,提供者一般用 CDN(Content Delivery Network)发布资源。CDN 是一种分布式的内容发布系统,相当于在世界各地都存了一份资源,有人需要的时候就就近送达。之前 Hexo-Next 主题默认用的 jsdelivr。

现在必须找个替代了,我找到了字节的免费 CDN,https://cdn.bytedance.com/。也算用下老东家的东西。

接下来只需要在 Hexo 主题的 _config.yml 里,找到 CDN 的部分然后改成这样:

1
2
3
4
5
6
7
8
# Script Vendors. Set a CDN address for the vendor you want to customize.
# Be aware that you would better use the same version as internal ones to avoid potential problems.
# Remember to use the https protocol of CDN files when you enable https on your site.
vendors:
# ...
# MathJax
# mathjax: //cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
mathjax: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js

不过字节 CDN 给的链接有 expire-1-M 的字样,难道每个月都要更新链接?先用着看看,反正现在是好了。

Fixed
阅读全文 »

好久好久没有更新博客了,大概是因为最近完全没有学习(恼)。今年大四,九月初还在字节实习的时候就已经弄完了夏令营,待 28 号填完推免系统,基本是确定了 PKU 直博,做系统虚拟化方向,算是一件喜事。接下来,直到大四上学期快结束,除了健身也没做什么有意义的事,那就在这里忏悔一下。

推免系统关了,当时除了整活居然没截图,所以我失去了一份重要时刻的证明,那就放一张夏令营的截图吧。

PKUAdmissionSite

希望接下来能不断推动自己进步。

ReferralSite
阅读全文 »

前言(考试前)

开始复习 CVPR 的时候 CVPR 大佬,你交校友孙剑博士去世了,RIP。以后无论水平高低出身贵贱,都得先养好身体。

这门课的老师是苏远歧老师,由于之前在 UPenn 带同一门课所以基本可以算高端课程的减负版(但是相比之下还是作业很多笑死),想要上课学本事的非常建议选!

前言(考试后)

快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑快跑vvvvvv

前言(出分了)

竟然意外地不错。

看来老师 Norm 了(笑)。

符号版式说明

考虑到排版规范和编写便利性、可读性,后文的符号版式说明如下

阅读全文 »

这个课老师纯念 PPT,要命的是 PPT 做得很烂,懂得都懂

这次我做的笔记仅供回忆知识点用,先学会比较好

建议看一遍 Database System Concepts 来真正学习数据库原理

考试回忆

考试回忆里可能着重列一些我场上觉得不是很确定的题,难度参考下就得了

  1. 填空(15):十五个空,考了如何由前趋图判断无法冲突串行等价(有环)
  2. 选择(15):十五题,有锁相容矩阵、事务 UNDO REDO
  3. 简答(9):三个题,非常坑,得理解一下再知道要列什么,老师说只需要列出概念不用详细解释;考了六级模型五级映像、查询优化分类、约束实现(CHECK 字句,断言,存储过程,触发器)
  4. 大题:计算关系代数、关系演算转换关系代数、查询优化
  5. 大题:SQL 查询
  6. 大题:判断范式,最小表示、求候选键、3NF 分解
  7. 大题(15):画 ER 图

纯背诵合集

定义

数据库(DB):是长期储存在计算机内、有组织的、可共享的大量数据的集合

数据库管理系统(DBMS):为建立、使用和维护数据库而配置的通用软件系统,是整个数据库系统的核心

阅读全文 »

结构按照著名坑导 BJP 的 PPT 整理,不代表作者同意其中任何内容,重要部分(如 BP)以及 PPT 啥都没讲的(如 OPTICS)按我的知识而不是 PPT 整理

考试回忆

很水,感觉是拍脑袋出题。六个大题

  1. 欠拟合怎么发现怎么解决
  2. 举三个人脸识别的算法,简单描述过程
  3. KNN 优缺点?K 值过大过小怎么办
  4. 你的机器学习方法精度上不去怎么办
  5. 给一个单隐层网络,算 BP 后权重更新值的形式
  6. 给四条离散数据,求最大信息增益的属性

概述

大数据:在可接受的时间内,无法用单机系统完整处理的数据

  • 大数据处理:分治,特定场景优化,并行,异构,弹性,横向扩展,容错
  • Hadoop 离线 Map Reduce;Spark 迭代式;Storm 流式在线实时

机器学习(ML),数据挖掘(DM),知识发现(KDD)

数据挖掘基本任务:描述性(挖掘模式),预测性(给出值)

机器学习基本任务:分类,聚类,预测,联想,优化;生成一个数据空间到目标空间的映射 \(S\to Z\)

阅读全文 »

这门课我在 XJTU 大三下学期上的,老师是可爱的罗敏楠老师,用的课本是著名的《人工智能——一种现代的方法》

考试回忆

八个题

  1. 填空题,被坑到了,有一个题填的是 \(h(n)\) 可采纳时 树搜索 的 A* 算法最优;\(h(n)\) 可采纳且一致时 图搜索 的 A* 算法最优。下面没整理到,我自然就不会了(这里有一点点小争议,图上 A* 搜索若有 \(h(n)\) 一致则不需要重新访问节点;而且这个题挖空挖得很难想到)
  2. 无信息搜索,让画二叉树,写出深度限制和迭代加深搜索的节点序列
  3. 有信息搜索,画出北京地铁北京站到西四的 A* 搜索树
  4. CSP,写弧相容过程
  5. 概率论,给了所有条件概率,算一些概率(简单)
  6. 概率推理,贝叶斯网络推理,不过是解析的而不是数值的,网络结构很小,挺有意思
  7. 时序推理,一阶马尔可夫,不过证据变量一共有四个值(两个布尔变量),算 \(t=1,2,3\) 滤波和平滑
  8. 决策,默写 Expected Utility 公式,顺便考了理性定义,最后给了个不深的例子让求 EU

考试两个半小时,但我看不到表,所以前五题不紧不慢写了一个半小时,老师提醒的时候还有三个大题,直接绷不住了。写完刚好交卷。

Agent

Agent 通过传感器感知环境并通过执行器对环境产生影响。

  • Agent 函数 \(f:P^*\to A\),其中 \(P^*\) 为感知序列,\(A\) 为行动;
  • Agent 程序实现 Agent 函数;
  • Agent 程序在 Agent 体系结构上执行。

理性:对每一个可能的感知序列,根据已知的感知序列提供的证据和 Agent 具有的先验知识,理性 Agent 应该选择能够使其性能度量最大化的行动。判断理性依赖于:性能度量、先验知识、行动、感知序列。

任务环境 PEAS (Performance, Environment, Actuators, Sensors)

阅读全文 »

SDN 老师出了一道不明所以的实机实验题,要求模拟一个特定的 TCP 传输过程,中途丢掉某个特定的包。

拔网线大概会直接丢所有的包,后来要求收到的包就模拟不出来了,而且十分考验手速。或者使用现有的防火墙程序,但按内容匹配也不容易。另一种方式是使用 mininet,笔者不太会 mininet。不过正好笔者了解过 eBPF,也正要学习,于是用 eBPF 写一个 XDP 防火墙,支持内容匹配。

我们的目的是用 BPF 实现一个 XDP(eXpress Data Path)程序,绑定在本机 loopback 接口上,匹配到 A 到 B 内容为 Are you OK? 的包,然后把它过滤掉。

不了解 eBPF 的话可以先看一下这篇博客 eBPF 技术介绍-刘达的博客

本文的 repo:eBPF-PayloadFilter

实现主机 A 和 B

使用 Socket 实现 TCP 连接已经老生常谈了,这次我们把它们绑定到 Loopback 接口;A 的端口 1145,B 的端口 5141,A 作为服务器。 experiment.c 的简化代码是这样的,错误处理省略掉了:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// experiment.c
#define A_PORT 1145
#define B_PORT 5141

void host_A() {
// SOCKET
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt));
// BIND to 1145
struct sockaddr_in address;
int addrlen = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(A_PORT);
bind(server_fd, (struct sockaddr *)&address,
sizeof(address));
// LISTEN
listen(server_fd, 3);
// ACCEPT
int new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen));

char buffer[1024] = {0};
char *hello = "Hello!", *areuok = "Are you OK?";
// A sends "Hello!"
send(new_socket, hello, strlen(hello), 0);
// After ACK, A sends "Are you OK?"
send(new_socket, areuok, strlen(areuok), 0);
// B sends "Hello!"
int valread = read(new_socket, buffer, 1024);
}

void host_B() {
// SOCKET
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
// BIND to 5141
struct sockaddr_in cli_addr;
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = htons(B_PORT);
bind(client_fd, (struct sockaddr *)&cli_addr, sizeof(cli_addr));
// CONNECT to localhost:1145
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(A_PORT);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
connect(client_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

char buffer[1024] = {0};
// B reads "Hello!" and ACK
int valread = read(client_fd, buffer, 1024);
// B sends "Hello!"
char *hello = "Hello!";
send(client_fd, hello ,strlen(hello) ,0);
// B reads "Are you OK?" and ACK
valread = read(client_fd, buffer, 1024);
}

int main(int argc, char const *argv[]) {
int B_pid = fork();
if (B_pid == 0) { // B
sleep(1); // Let A start first
host_B();
}
else { // A
host_A();
}
return 0;
}

eBPF 工具链准备

既然是 eBPF,必须是 Linux 了,Win 和 MacOS 不好使。

阅读全文 »
0%