小菜鸟

java菜鸟号正在起航

Python 变量作用域:变量在哪儿能用,Python 按这个顺序找

写 Python 的时候,有时候会遇到这种奇怪的情况:

明明在外面定义了一个变量,函数里一用就报错 UnboundLocalError;或者在函数里改了一个值,外面却纹丝不动。

这些问题都跟变量作用域有关——变量在哪儿能用,Python 是按照一套固定规则去查找的。

变量能找到,全靠 LEGB

Python 找变量的时候,按这个顺序找:局部 → 嵌套 → 全局 → 内置

记住四个字母:L → E → G → B

缩写 全称 啥意思 举个例子
L Local 当前函数里定义的变量 函数内部的 x = 1
E Enclosing 外层函数的变量(嵌套函数场景) 外函数里的 x,内函数能用
G Global 模块顶层的变量 .py 文件最外面定义的变量
B Built-in Python 自带的函数和变量 printlenrange

从里往外找,找到了就用,找不到就报 NameError

局部变量(Local):函数里面的,外面用不了

函数里面定义的变量,默认就是局部变量。只在函数执行期间存在,执行完就没了。

def my_func():
    local_var = 10
    print(local_var)   # 10

my_func()
# print(local_var)   # NameError: name 'local_var' is not defined

函数的参数也是局部变量:

def greet(name):   # name 是参数,也是局部变量
    print(name)

greet("Alice")
# print(name)   # 报错,外面访问不到
阅读全文 »

Python 函数:写了这么多年,这几个参数用法你未必全用过

函数是 Python 里最基础的代码组织方式。把一段逻辑包起来,起个名字,需要的时候调用一下——就这么简单。

但 Python 函数的参数系统比大多数语言都灵活,位置参数、默认参数、关键字参数、*args、\kwargs**,一套下来能覆盖各种调用场景。

最基本的:定义和调用

def 定义一个函数,括号里放参数,冒号后面缩进写函数体。

def say_hello():
    print("Hello, Python!")

say_hello()   # 调用,记得加括号

带参数的:

def print_max(a, b):
    if a > b:
        print(f"{a} 更大")
    else:
        print(f"{b} 更大")

print_max(5, 7)   # 7 更大

跟 Java 的方法比起来,Python 函数有几个明显不一样的地方:

  • 不需要声明返回值类型
  • 可以返回多个值(本质是返回元组)
  • 参数传递非常灵活(下面重点讲)

参数系统:五种参数,各有各的用途

1. 位置参数:最基础的,按顺序传

最基本的参数类型,调用时必须按定义顺序传递。

def introduce(name, age, city):
    print(f"{name}, {age}岁, 来自{city}")

introduce("Alice", 20, "Beijing")   # 必须按顺序

没什么好说的,大多数函数都是这么写的。缺点就是调用的时候必须记住顺序,参数多了容易搞混。

2. 默认参数:给参数一个”备用值”

def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")        # Hello, Alice!
greet("Bob", "Hi")    # Hi, Bob!

这个特性解决的是:大多数情况下用默认值,偶尔需要定制。比如日志函数,默认级别是 INFO,但特殊场景可以传 ERROR。

注意一个坑:默认参数在函数定义时就被创建了,如果用可变对象(列表、字典)当默认值,会出问题。 后面会说怎么解决。

阅读全文 »

Python 字典:你每天都会用到的”通讯录”

写 Python 代码,字典(Dictionary)是我用得最多的数据结构,没有之一。

它就是一个通讯录:你记一个人的名字(键),就能找到他的电话号码(值)。存什么都能快速找到,这就是字典的价值。

字典长什么样?怎么建?

字典用大括号 {},里面是”键:值”的配对,逗号隔开。

# 基本字典(键为字符串,值为整数)
student = {'name': 'Alice', 'age': 20, 'major': 'Computer Science'}

# 键可以是任意不可变类型(如整数、字符串、元组)
mixed_dict = {
    1: 'one',          # 整数作为键
    ('a', 'b'): 123,   # 元组作为键(元组不可变)
    'list': [1, 2, 3]  # 值可以是任意类型(包括列表、字典等)
}

# 空字典
empty_dict = {}
# 用 dict() 函数创建字典
another_dict = dict(name='Bob', age=21)  # 等价于 {'name': 'Bob', 'age': 21}

两个规则记住就行:

  • 键必须是不可变的。字符串、数字、元组都可以,列表不行。因为列表能变,Python 没法保证它”始终能代表同一个东西”。
  • 键不能重复。你如果写了两次同一个键,后面的会覆盖前面的。

增删改查,字典的”四件套”

查:用 [] 或者 get()

阅读全文 »

Python 列表和元组到底有啥区别?别死记硬背,看场景选就行

核心区别一句话总结:列表可变,元组不可变。这一差异决定了它们各自的应用场景和性能特性。

刚开始学 Python 的时候,我总搞不清列表和元组啥时候用哪个。明明都能存一串东西,干嘛整两个?

后来写多了就明白了:列表是”活”的,元组是”死”的。列表能改能删能加,元组定下来就动不了了。

列表:能增能删能改,最常用的”筐”

列表用方括号 [],啥都能往里面放,数字、字符串、布尔值、甚至另一个列表。

基本定义与创建

# 空列表
empty_list = []
# 包含不同类型元素的列表(Python 列表支持异构元素)
mixed_list = [1, "apple", 3.14, True]
# 嵌套列表(列表中包含列表)
nested_list = [1, [2, 3], [4, [5, 6]]]

访问元素

通过索引(下标)访问元素,索引从 0 开始,支持负数索引(从末尾计数,-1 表示最后一个元素)。

fruits = ["apple", "banana", "cherry", "date"]

# 访问单个元素
print(fruits[0])   # 输出:apple(第一个元素)
print(fruits[-1])  # 输出:date(最后一个元素)

# 分片(切片):获取子列表,语法为 [start:end:step],左闭右开
print(fruits[1:3])   # 输出:['banana', 'cherry'](索引1到2的元素)
print(fruits[:2])    # 输出:['apple', 'banana'](从开头到索引1)
print(fruits[2:])    # 输出:['cherry', 'date'](从索引2到结尾)
print(fruits[::2])   # 输出:['apple', 'cherry'](步长为2,间隔一个元素)

# 复制列表(创建副本,修改副本不影响原列表)
fruits_copy = fruits[:]

# 获取元素对应索引
index = fruits.index(target)

切片这个规则刚开始容易晕,记住 [start:end] 取的是 start 到 end-1 就行了。

修改元素

列表是可变的,直接通过索引修改元素:

阅读全文 »

pdb调试器

python dis操作(反汇编) python -m dis “print(‘hello’)”

矩阵求导?

线性回归->逻辑回归、Scikit-Learn 二分类、多分类(OVO/OVR/MVM、softmax)。如果不是分类问题的话,是什么问题呢

损失函数:极大似然估计、相对熵、交叉熵

正则化

涌现能力?

神经网络是在做特征提取

图像进行稀疏编码

softmax计算概率

位置编码 Learned/RoPE/ALiBi/Relative

激活函数有哪些?大模型们选择了哪个 GELU/ReLU/SwiGLU

归一化?归一化的位置?

混合专家架构MOE?中间有个路由,去判断该由哪个专家去处理

关于如何保证Router均衡地路由到不同专家,这个问题问得非常棒!业界通用的做法是引入负载均衡损失(Load Balancing Loss)。以DeepSeek模型为例,会在训练的Loss函数中加入一个辅助项,监控每个专家的使用频率。当一个专家被分配了过多的token时,它产生的惩罚Loss就会变大。这样在反向传播更新权重时,Router就会调整自身的网络参数,避免过度依赖该专家,强制将token均衡分配给其他专家。

长上下文的难点在哪?

训练的参数:批次大小、学习率、预热、衰减、优化器adam(adam_beta1: Adam系列优化器中一阶矩估计(动量)的指数衰减率。默认为0.9。 adam_beta2: Adam系列优化器中二阶矩估计(方差)的指数衰减率。默认为0.95。 adam_epsilon: Adam系列优化器中用于数值稳定性的epsilon值。默认为1e-8。 )、权重衰减、梯度裁剪

如何进行蒸馏?白箱蒸馏是什么?

KTransformers

Deepseek 开源的几个项目、llama开源项目

MCP、function call

大模型怎么解析图片(VIT) 用的是编码器?

DeepResearch是什么?怎么个结构,多智能体开发

微调所需要的硬件怎么计算,dense、moe

强化学习

多机多卡如何进行训练

多模态模型如何进行微调?投影层(投影层负责把图像翻译成文字)

DBSCAN 本身并没有被直接嵌入到大模型的训练或推理架构中(你不会在 Transformer 的代码里找到 DBSCAN),但在大模型的研究、评估和数据工程环节,它正变得越来越重要。

简单来说:DBSCAN 不是大模型的”零件”,而是大模型生态中的”诊断工具”和”数据过滤器”。

以下是 DBSCAN 在大模型领域最核心的几个应用场景:

1. 模型内部表征分析(Mechanistic Interpretability)

这是目前最前沿的用法。研究者将大模型中间层的隐藏状态提取出来,用 DBSCAN 进行聚类,以理解模型”学到了什么”。

  • 发现语义簇:对同一层不同 token 的 embedding 做 DBSCAN,可以发现模型是否自发地将语法类别(名词/动词)、情感倾向、甚至事实知识编码成了独立的稠密簇。
  • 识别异常激活:DBSCAN 天然能识别噪声点(标记为 -1)。如果某些 token 的表征无法归入任何簇,往往意味着模型在该处出现了”困惑”或错误处理,这对定位幻觉(Hallucination)有重要价值。
  • 对比不同模型:比较两个模型在同一任务上的表征聚类结构,可以量化它们的”认知差异”。

💡 为什么选 DBSCAN 而不是 K-Means?
大模型的表征空间是高维且高度非凸的,簇的形状不规则、数量未知。K-Means 假设球形簇且需预设 K 值,在这种场景下几乎失效;而 DBSCAN 基于密度、无需预设 K、能发现任意形状的簇,完美适配神经网络表征的几何特性。

2. 训练数据去重与质量过滤

大模型训练数据动辄数万亿 token,其中包含大量重复和低质内容。DBSCAN 在这里扮演关键角色:

  • 语义级去重:先对文本做 embedding,再用 DBSCAN 聚类。同一个高密度簇内的样本高度相似,只保留代表性样本即可大幅减少冗余,同时避免过度删除(相比精确哈希匹配更鲁棒)。
  • 低质/有害数据识别:低质量文本(如乱码、机器生成垃圾)在嵌入空间中往往形成稀疏区域或被标记为噪声点,可以直接过滤。
  • 课程学习排序:根据簇的密度安排训练顺序——先学高密度簇(简单、典型样本),再学低密度区域(困难、边缘样本),已被证明能提升收敛效率。

3. 评估与基准测试构建

  • 自动构建评测集:对海量未标注数据做 DBSCAN 聚类,从每个簇中采样代表性样本,可以自动生成覆盖多样化的评测基准,避免人工标注偏差。
  • 输出多样性评估:对模型生成的多个回答做 embedding + DBSCAN,簇的数量直接反映生成多样性;如果所有回答都落入同一个簇,说明模型陷入了模式崩塌。

4. RAG 系统中的知识组织

在检索增强生成中,DBSCAN 用于对知识库文档块进行语义聚类:

  • 自动发现知识主题,辅助构建层次化索引
  • 检索时先在簇级别粗筛,再在簇内精排,提升召回效率和准确性

⚠️ 重要澄清:容易混淆的概念

概念 是否等于 DBSCAN 说明
Tokenizer 中的 BPE 基于字节对合并,是确定性算法,与密度聚类无关
MoE 的路由机制 通常用 Top-K gating 或负载均衡损失,不是 DBSCAN
向量数据库的 ANN 搜索 HNSW/IVF 等近似最近邻算法,用于检索而非聚类
RLHF 中的奖励模型聚类 ⚠️ 偶尔 少数研究用 DBSCAN 分析偏好数据的分布结构

💡 总结

DBSCAN 在大模型中不参与前向传播和反向传播,但它是理解和治理大模型不可或缺的外部分析工具。随着可解释性研究和数据工程的重要性日益凸显,DBSCAN(及其高维变体如 HDBSCAN)在大模型生态中的地位正在快速上升。如果你从事大模型研究或数据工程,掌握 DBSCAN 在高维嵌入空间中的应用是一项非常有价值的技能。

0%