2025

163 posts

TypeScript as const

在理解 `as const` 的优点前,我们先看看如何分别用枚举和字面量类型来表示一个 `LogLevels`。 我们可以这样枚举 `LogLevels`: ```typescript enum LogLevelEnum { Debug = "DEBUG", Info = "INFO", } ``` 这样做的好处是:`LogLevelEnum`...

TypeScript: Type vs. Interface

在 TypeScript 中,`type` 和 `interface` 是两种定义类型的主要方式。它们在很多情况下功能相似,但在关键方面存在差异。下面系统梳理一下它们的相同点与不同点,以及使用的最佳实践。 在定义对象的形状或函数签名时,`type` 和 `interface` 的语法和功能几乎相同。两者都可以用来描述一个对象应该包含哪些属性和方法与定义一个函数的类型签名。。...

TypeScript 泛型

在开发过程中,我们经常会遇到需要编写功能相同、但处理的数据类型不同的组件(如函数或类)。比如下面的队列: ```typescript class QueueOfNumbers { private queue: number[] = []; public push(value: number): void { this. push(value); } public pop(): number...

线性方程

在前面的线性代数基础中,我们提到了下面的方程: $$ \begin{aligned} x - 2y &= 1\\ 3x + 2y &= 11 \end{aligned} $$ 可以写作向量的线性组合: $$ \begin{aligned} x\begin{bmatrix}1\\[4pt]3\end{bmatrix} +...

线性代数基础

在行图像中,每一个方程都代表一个几何图形。以二维空间为例,下面的方程: $$ \begin{aligned} 2x - y &= 0\\ -x + 2y &= 3 \end{aligned} $$ 在行图像的视角可以如下理解: - 第一个方程 $2x - y = 0$ 是 $x$-$y$ 平面上代表一条直线。 - 第二个方程 $-x + 2y = 3$ 是平面上的另一条直线。 -...

TypeScript Mixin

在经典的面向对象编程中,我们经常使用继承的方法:创建一个通用的基类,然后扩展它以创建更特化的类。然而,这种模型有其局限性。如果我们想从两个或多个不相关的类中组合功能,该怎么办?TypeScript 和 JavaScript 一样,**只允许一个类扩展单个父类**。这就是“**组合优于继承**”原则发挥作用的地方。而 Mixin 即是实现这一目标的强大模式。...

TypeScript 装饰器

装饰器模式是一种结构型设计模式,它允许我们**在运行时动态地向一个对象添加新的行为和职责**,同时又不改变其结构。 这种模式的核心优势在于它遵循了“开闭原则”:对扩展开放,对修改关闭。我们可以在不修改现有代码的情况下,为其增添新功能。 在 TypeScript 和 JavaScript (ES2022+) 中,装饰器是这一设计模式的语法糖。它是一种特殊的函数,以 `@expression`...

lr-shedule

Write your blog post content here. This is a new blog post...

批归一化补充

批归一化的理论知识与实现在[之前 CS289 的作业中](https://fyerfyer. dev/blog/cs289-hw6-code/)已经有详细讲解了,这里谈论下对批归一化的一些理解。 批标准化(BN)能够稳定网络,从而允许使用远高于常规的学习率进行训练,而不会导致模型发散(即训练失败)。 我们使用 CIFAR-10 数据集做下面这个简单的实验: ```python def...

参数初始化

在前面的笔记中,我们提到了梯度爆炸与梯度消失的问题: - 如果梯度连乘项中的每一个因子都小于 1,那么一长串小于 1 的数字相乘,结果会以指数级速度缩小,迅速趋近于 0。 - 如果梯度连乘项中的每一个因子都大于 1,那么一长串大于 1 的数字相乘,结果就会以指数级速度增大,变得异常巨大。 导致这些现象的根本原因在于不恰当的信号流。而我们可以**用方差来衡量信号的强度**: - 方差接近于...