华为C语言编程规范(摘录)
总体原则:清晰第一,简洁为美,与原有代码风格保持一致。
函数:
- 一个函数只完成一个功能。
- 避免函数过长,建议不超过50行代码。
- 函数的代码块嵌套不超过4层。
标识符命名与定义:
- 命名应清晰、明了,避免缩写和汉语拼音。
- 全局变量名前加
g_
前缀,静态变量名前加s_
前缀。- 避免单字节命名变量,除非是循环变量。
变量:
- 一个变量只用于一个功能。
- 避免使用全局变量,如果必须使用,应定义为
static
。- 防止局部变量与全局变量同名。
注释:
- 注释应清晰、明了,含义准确。
- 注释应在代码的功能、意图层次上,而不是简单重复代码。
排版与美观:
- 使用统一的缩进风格,每级缩进4个空格。
- 相对独立的程序块之间、变量说明之后必须加空行。
代码编辑、编译:
- 使用编译器的最高告警级别,消除所有告警。
《数学之美》 第4章 谈谈分词
大模型如今已深入我们的日常学习和工作中,但是在一些在我们看来格外简单的问题上,大模型却给出了令人大跌眼镜的答案,例如最近很火的关于“为什么AI数不清Strawberry里有几个 r?”的讨论,普遍认为这与「Token 化(Tokenization)」有关。
为什么大模型要使用token?其在大模型中扮演怎样的角色?这是我在阅读这一章前想要了解的。
机器如何对自然语言进行处理?显然机器不能直接理解自然语言,因此我们需要先对一串文本进行「分词」操作,将本来很长很长的句子切分为一个个的Token,即文本的基本单位。
如何划分token?
对于单词本身就相隔的英文来说,只需要以空格作为划分标志即可。但对于没有明显划分的汉字来说,这个问题就要复杂得多。
在最开始,我们从语言学的角度去划分,称为「查字典」。
顾名思义,我们总结出一本《词语大全》,从文本的开头开始,对照《词语大全》一一进行匹配。例如,
第三十三届 / 夏季 / 奥运会 / 在 / 法国 / 巴黎 / 举行
这个方法足够简单,但存在以下缺点:
对于“发展中国家”,按照从左到右查字典的方法,将被划分为 发展 / 中国 / 家
那是不是选择最长的词组,就可以解决问题了呢?当我拿出以下句子:
对于“上海大学城书店”,将被划分为 上海大学 / 城 / 书店
由于语言中本身就存在歧义,就像学者们对于古文的断句说法不一,一旦遇到这种情况,单纯查字典的方法就不行了。
如何解决「语义二义性」的问题?
当我们看到“发展中国家”,我们会认为这是一个词,同样的对于“上海大学城书店”,我们的第一反应是“上海 / 大学城 / 书店”,因为现实生活中几乎没有人会说“发展 / 中国 / 家”或是“上海大学 / 城 / 书店”。受此启发,我们可以转换思路——找出分词后句子出现概率最大的,即借助「统计语言模型」——来改进查字典法。
当然如果要穷举所有分词方法,计算量会比较大。不过我们可以使用「动态规划(Dynamic Programming)」和「维特比算法(Viterbi)」的技巧,快速找到最佳分词。
这样,就较好地解决了语义二义性问题。
颗粒度?
另外,分词还存在一个 「颗粒度」问题。
对于“广东外语外贸大学”,可以有以下几种划分:
①广东外语外贸大学
②广东 / 外语外贸 / 大学
③广东 / 外语 / 外贸 / 大学
其中①颗粒度最粗,③颗粒度最细。
对于不同的应用场景,应当选择适合的颗粒度:
如机器翻译,最好使用粗颗粒度,将“广东外语外贸大学”视为一个整体进行翻译。
如搜索引擎,则采用细颗粒度,当我们只输入“外语外贸”,也可查询到“广东外语外贸”的词条。
以上,我们可以说,分词是大模型的基础,是整个模型架构和功能的基石。没有Token的划分和处理,模型将无法有效地处理和理解文本数据,也无法生成有意义的自然语言输出。
再回到一开始的例子,strawberry 这个单词就被分为了 str-aw-berry 三个 token,对于AI而言,它看到的是🌱😲🍓(用emoji打个比方),而不是 s-t-r-a-w-b-e-r-r-y。当我们明确要求AI罗列出一个个字母,并统计“r”出现的次数后,AI就能给出正确的答案。