数学基础
- 线性代数
- 概率论与随机过程
- 数值计算
- 蒙特卡洛方法与 MCMC 采样
- 机器学习方法概论
统计学习
深度学习
- 深度学习简介
- 深度前馈网络
- 反向传播算法
- 正则化
- 深度学习中的最优化问题
- 卷积神经网络
- CNN:图像分类
- 循环神经网络 RNN
- Transformer
- 一、Transformer [2017]
- 二、Universal Transformer [2018]
- 三、Transformer-XL [2019]
- 四、GPT1 [2018]
- 五、GPT2 [2019]
- 六、GPT3 [2020]
- 七、OPT [2022]
- 八、BERT [2018]
- 九、XLNet [2019]
- 十、RoBERTa [2019]
- 十一、ERNIE 1.0 [2019]
- 十二、ERNIE 2.0 [2019]
- 十三、ERNIE 3.0 [2021]
- 十四、ERNIE-Huawei [2019]
- 十五、MT-DNN [2019]
- 十六、BART [2019]
- 十七、mBART [2020]
- 十八、SpanBERT [2019]
- 十九、ALBERT [2019]
- 二十、UniLM [2019]
- 二十一、MASS [2019]
- 二十二、MacBERT [2019]
- 二十三、Fine-Tuning Language Models from Human Preferences [2019]
- 二十四 Learning to summarize from human feedback [2020]
- 二十五、InstructGPT [2022]
- 二十六、T5 [2020]
- 二十七、mT5 [2020]
- 二十八、ExT5 [2021]
- 二十九、Muppet [2021]
- 三十、Self-Attention with Relative Position Representations [2018]
- 三十一、USE [2018]
- 三十二、Sentence-BERT [2019]
- 三十三、SimCSE [2021]
- 三十四、BERT-Flow [2020]
- 三十五、BERT-Whitening [2021]
- 三十六、Comparing the Geometry of BERT, ELMo, and GPT-2 Embeddings [2019]
- 三十七、CERT [2020]
- 三十八、DeCLUTR [2020]
- 三十九、CLEAR [2020]
- 四十、ConSERT [2021]
- 四十一、Sentence-T5 [2021]
- 四十二、ULMFiT [2018]
- 四十三、Scaling Laws for Neural Language Models [2020]
- 四十四、Chinchilla [2022]
- 四十七、GLM-130B [2022]
- 四十八、GPT-NeoX-20B [2022]
- 四十九、Bloom [2022]
- 五十、PaLM [2022] (粗读)
- 五十一、PaLM2 [2023](粗读)
- 五十二、Self-Instruct [2022]
- 句子向量
- 词向量
- 传统CTR 预估模型
- CTR 预估模型
- 一、DSSM [2013]
- 二、FNN [2016]
- 三、PNN [2016]
- 四、DeepCrossing [2016]
- 五、Wide 和 Deep [2016]
- 六、DCN [2017]
- 七、DeepFM [2017]
- 八、NFM [2017]
- 九、AFM [2017]
- 十、xDeepFM [2018]
- 十一、ESMM [2018]
- 十二、DIN [2017]
- 十三、DIEN [2019]
- 十四、DSIN [2019]
- 十五、DICM [2017]
- 十六、DeepMCP [2019]
- 十七、MIMN [2019]
- 十八、DMR [2020]
- 十九、MiNet [2020]
- 二十、DSTN [2019]
- 二十一、BST [2019]
- 二十二、SIM [2020]
- 二十三、ESM2 [2019]
- 二十四、MV-DNN [2015]
- 二十五、CAN [2020]
- 二十六、AutoInt [2018]
- 二十七、Fi-GNN [2019]
- 二十八、FwFM [2018]
- 二十九、FM2 [2021]
- 三十、FiBiNET [2019]
- 三十一、AutoFIS [2020]
- 三十三、AFN [2020]
- 三十四、FGCNN [2019]
- 三十五、AutoCross [2019]
- 三十六、InterHAt [2020]
- 三十七、xDeepInt [2023]
- 三十九、AutoDis [2021]
- 四十、MDE [2020]
- 四十一、NIS [2020]
- 四十二、AutoEmb [2020]
- 四十三、AutoDim [2021]
- 四十四、PEP [2021]
- 四十五、DeepLight [2021]
- 图的表达
- 一、DeepWalk [2014]
- 二、LINE [2015]
- 三、GraRep [2015]
- 四、TADW [2015]
- 五、DNGR [2016]
- 六、Node2Vec [2016]
- 七、WALKLETS [2016]
- 八、SDNE [2016]
- 九、CANE [2017]
- 十、EOE [2017]
- 十一、metapath2vec [2017]
- 十二、GraphGAN [2018]
- 十三、struc2vec [2017]
- 十四、GraphWave [2018]
- 十五、NetMF [2017]
- 十六、NetSMF [2019]
- 十七、PTE [2015]
- 十八、HNE [2015]
- 十九、AANE [2017]
- 二十、LANE [2017]
- 二十一、MVE [2017]
- 二十二、PMNE [2017]
- 二十三、ANRL [2018]
- 二十四、DANE [2018]
- 二十五、HERec [2018]
- 二十六、GATNE [2019]
- 二十七、MNE [2018]
- 二十八、MVN2VEC [2018]
- 二十九、SNE [2018]
- 三十、ProNE [2019]
- Graph Embedding 综述
- 图神经网络
- 一、GNN [2009]
- 二、Spectral Networks 和 Deep Locally Connected Networks [2013]
- 三、Fast Localized Spectral Filtering On Graph [2016]
- 四、GCN [2016]
- 五、神经图指纹 [2015]
- 六、GGS-NN [2016]
- 七、PATCHY-SAN [2016]
- 八、GraphSAGE [2017]
- 九、GAT [2017]
- 十、R-GCN [2017]
- 十一、 AGCN [2018]
- 十二、FastGCN [2018]
- 十三、PinSage [2018]
- 十四、GCMC [2017]
- 十五、JK-Net [2018]
- 十六、PPNP [2018]
- 十七、VRGCN [2017]
- 十八、ClusterGCN [2019]
- 十九、LDS-GNN [2019]
- 二十、DIAL-GNN [2019]
- 二十一、HAN [2019]
- 二十二、HetGNN [2019]
- 二十三、HGT [2020]
- 二十四、GPT-GNN [2020]
- 二十五、Geom-GCN [2020]
- 二十六、Graph Network [2018]
- 二十七、GIN [2019]
- 二十八、MPNN [2017]
- 二十九、UniMP [2020]
- 三十、Correct and Smooth [2020]
- 三十一、LGCN [2018]
- 三十二、DGCNN [2018]
- 三十三、AS-GCN
- 三十四、DGI [2018]
- 三十五、DIFFPOLL [2018]
- 三十六、DCNN [2016]
- 三十七、IN [2016]
- 图神经网络 2
- 图神经网络 3
- 推荐算法(传统方法)
- 一、Tapestry [1992]
- 二、GroupLens [1994]
- 三、ItemBased CF [2001]
- 四、Amazon I-2-I CF [2003]
- 五、Slope One Rating-Based CF [2005]
- 六、Bipartite Network Projection [2007]
- 七、Implicit Feedback CF [2008]
- 八、PMF [2008]
- 九、SVD++ [2008]
- 十、MMMF 扩展 [2008]
- 十一、OCCF [2008]
- 十二、BPR [2009]
- 十三、MF for RS [2009]
- 十四、 Netflix BellKor Solution [2009]
- 推荐算法(神经网络方法 1)
- 一、MIND [2019](用于召回)
- 二、DNN For YouTube [2016]
- 三、Recommending What Video to Watch Next [2019]
- 四、ESAM [2020]
- 五、Facebook Embedding Based Retrieval [2020](用于检索)
- 六、Airbnb Search Ranking [2018]
- 七、MOBIUS [2019](用于召回)
- 八、TDM [2018](用于检索)
- 九、DR [2020](用于检索)
- 十、JTM [2019](用于检索)
- 十一、Pinterest Recommender System [2017]
- 十二、DLRM [2019]
- 十三、Applying Deep Learning To Airbnb Search [2018]
- 十四、Improving Deep Learning For Airbnb Search [2020]
- 十五、HOP-Rec [2018]
- 十六、NCF [2017]
- 十七、NGCF [2019]
- 十八、LightGCN [2020]
- 十九、Sampling-Bias-Corrected Neural Modeling [2019](检索)
- 二十、EGES [2018](Matching 阶段)
- 二十一、SDM [2019](Matching 阶段)
- 二十二、COLD [2020 ] (Pre-Ranking 模型)
- 二十三、ComiRec [2020](https://www.wenjiangs.com/doc/0b4e1736-ac78)
- 二十四、EdgeRec [2020]
- 二十五、DPSR [2020](检索)
- 二十六、PDN [2021](mathcing)
- 二十七、时空周期兴趣学习网络ST-PIL [2021]
- 推荐算法之序列推荐
- 一、FPMC [2010]
- 二、GRU4Rec [2015]
- 三、HRM [2015]
- 四、DREAM [2016]
- 五、Improved GRU4Rec [2016]
- 六、NARM [2017]
- 七、HRNN [2017]
- 八、RRN [2017]
- 九、Caser [2018]
- 十、p-RNN [2016]
- 十一、GRU4Rec Top-k Gains [2018]
- 十二、SASRec [2018]
- 十三、RUM [2018]
- 十四、SHAN [2018]
- 十五、Phased LSTM [2016]
- 十六、Time-LSTM [2017]
- 十七、STAMP [2018]
- 十八、Latent Cross [2018]
- 十九、CSRM [2019]
- 二十、SR-GNN [2019]
- 二十一、GC-SAN [2019]
- 二十二、BERT4Rec [2019]
- 二十三、MCPRN [2019]
- 二十四、RepeatNet [2019]
- 二十五、LINet(2019)
- 二十六、NextItNet [2019]
- 二十七、GCE-GNN [2020]
- 二十八、LESSR [2020]
- 二十九、HyperRec [2020]
- 三十、DHCN [2021]
- 三十一、TiSASRec [2020]
- 推荐算法(综述)
- 多任务学习
- 系统架构
- 实践方法论
- 深度强化学习 1
- 自动代码生成
工具
- CRF
- lightgbm
- xgboost
- scikit-learn
- spark
- numpy
- matplotlib
- pandas
- huggingface_transformer
- 一、Tokenizer
- 二、Datasets
- 三、Model
- 四、Trainer
- 五、Evaluator
- 六、Pipeline
- 七、Accelerate
- 八、Autoclass
- 九、应用
- 十、Gradio
Scala
- 环境搭建
- 基础知识
- 函数
- 类
- 样例类和模式匹配
- 测试和注解
- 集合 collection(一)
- 集合collection(二)
- 集成 Java
- 并发
二、算法原理
- 有三种常见的
subword tokenization
算法:Byte Pair Encoding: BPE
、WordPiece
、Unigram
。
1.1 BPE
Byte Pair Encoding: BPE
来自于论文《Neural Machine Translation of Rare Words with Subword Units》(2015)
。BPE
是一种简单的数据压缩技术,它迭代式地替换序列中最频繁的字节对。我们不是合并频繁的字节对,而是合并频繁的字符或字符序列。首先,我们用
character vocabulary
初始化symbol vocabulary
,将每个单词表示为一个字符序列,加上一个特殊的单词结束符</w>
,这允许我们在tokenization
后恢复原始的tokenization
。然后,我们迭代地计算所有
symbol pair
,并用新的symbol
'AB'
替换最频繁的symbol pair
('A','B')
。每个merge
操作产生一个新的symbol
,它代表一个character n-gram
。同时,每个
merge
代表一个规则。
最终的
symbol vocabulary
大小等于initial vocabulary
的大小,加上merge
操作的次数(这是算法唯一的超参数)。下面的显示了一个最小化的
Python
实现。在实践中,我们通过索引所有pair
并增量更新数据结构来提高效率:x import re, collections def get_stats(vocab): # vocab : 存储 word -> freq 的 dict ''' 计算词表中,字符的 2-gram 及其出现频次 ''' pairs = collections.defaultdict(int) for word, freq in vocab.items(): symbols = word.split() # 拆分为字符序列 for i in range(len(symbols)-1): pairs[symbols[i],symbols[i+1]] += freq # 计算字符的 2-gram 及其出现频次 return pairs def merge_vocab(pair, v_in): # pair 为最高频的 2-gram,v_in 为已有的 vocab ''' 利用最高频的 2-gram 来更新已有的词表 ''' v_out = {} bigram = re.escape(' '.join(pair)) # 对字符串中可能被解释为正则运算符的字符进行转义 p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)') # 编译一个正则模式 # \S 匹配任意非空字符 # (?<! \S) 前向否定界定符。当 bigram 之前不是任意非空字符之时,匹配成功 # (?! \S) 后向否定界定符。当 bigram 之后不是任意非空字符之时,匹配成功 for word in v_in: w_out = p.sub(''.join(pair), word) # 将word中已有的pair替换为紧凑版本(移除中间的空格) # 注意这里有两个 join(pair), 一个是 ' '.join() 带空格, 另一个是 ''.join() 不带空格 v_out[w_out] = v_in[word] return v_out
示例:
xxxxxxxxxx
vocab = {'l o w </w>' : 5, 'l o w e r </w>' : 2, # initial vocabulary 'n e w e s t </w>':6, 'w i d e s t </w>':3} num_merges = 10 for i in range(num_merges): pairs = get_stats(vocab) best = max(pairs, key=pairs.get) vocab = merge_vocab(best, vocab) print(best) # 最终 vocab: {'low</w>': 5, 'low e r </w>': 2, 'newest</w>': 6, 'wi d est</w>': 3}注意,初始的
vocab
已经将单词拆分为字符序列,并用' '
分隔。这个步骤被称作pre-tokenization
。在机器翻译任务上,有两种应用
BPE
的方法:学习两个独立的编码,一个用于
source vocabulary
、另一个用于target vocabulary
。这种方法的优点是:在文本和词表规模方面更紧凑,并且更能保证在相应语言的训练文本中看到每个
subword
单元。学习两个
vocabulary
的并集上的编码,称之为joint BPE
。这种方法的优点是:提高了
source tokenization
和target tokenization
之间的一致性。如果我们独立地应用BPE
,相同的name
在两种语言中可能被不同地tokenization
,这使得神经模型更难学习subword
单元之间的映射。
Byte-level BPE
:包含所有基础字符base character
的base vocabulary
可能非常大,例如,将所有unicode
字符(一共65536
个,即2
个字节的表示范围)作为基础字符。为了获得更小的
base vocabulary
,GPT-2
使用byte
作为base vocabulary
。这是一个聪明的技巧,它强制base vocabulary
的大小为256
(一个字节的表示范围),同时确保每个基本字符都包含在vocabulary
中。GPT-2
具有50257
的词表大小,其对应于256
个byte-base token
、一个特殊的文本结束token
、以及通过50000
次merge
所学到的symbol
。相比之下,使用传统
BPE
的GPT
的词表规模为40478
,其中包含478
个基本字符,并在40000
次merge
后停止训练。来自
Hugging Face
上的例子:假设在
pre-tokenization
之后,我们得到了如下的单词及其频次的集合:xxxxxxxxxx
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)将所有单词拆分到字符,则我们得到:
xxxxxxxxxx
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)此时
base vocabulary
为:xxxxxxxxxx
["b", "g", "h", "n", "p", "s", "u"]然后,
BPE
计算每个可能的symbol pair
,然后挑选出现频次最高的symbol pair
。此时,频次最高的
symbol pair
是:将"u"
后面跟着"g"
的symbol pair
合并为"ug"
。此时单词及其频次的集合为:
xxxxxxxxxx
("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)此时
base vocabulary
为:xxxxxxxxxx
["b", "g", "h", "n", "p", "s", "u", "ug"]BPE
然后确定下一个最常见的symbol pair
,即"u"
后面跟着"n"
。因此,BPE
将"u", "n"
合并为"un"
。下一个最常见的
symbol pair
,即"h"
后面跟着"ug"
。因此,BPE
将"h", "ug"
合并为"hug"
。此时单词及其频次的集合为:
xxxxxxxxxx
("hug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("hug" "s", 5)此时
base vocabulary
为:xxxxxxxxxx
["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"]
假设
BPE
的训练在这个时刻结束,那么所学习的所有merge rule
将被应用于新的单词。例如:- 单词
"bug"
被tokenized
为["b", "ug"]
。 - 单词
"mug"
被tokenized
为["<unk>", "ug"]
,因为symbol
"m"
不在base vocabulary
中。
1.2 WordPiece
与
BPE
一样,WordPiece
(《Japanese and korean voice search》(2012)
)从一个小的词汇表开始,并学习merge
规则。二者之间的区别在于merge
的方式不同:WordPiece
不是选择最高频的pair
,而是通过如下公式计算每个pair
的得分:其中:
$ t_1 $ 和 $ t_2 $ 为两个token
, $ t_{1,2} $ 为它们merge
之后得到的新的token
。 $ \text{freq}(t) $ 为token
$ t $ 在语料库中出现的频次。
选择
score
最高的一对token
等价于:其中:
$ N $ 为语料库中的token
总数。因此
WordPiece
的物理意义为:通过将 $ t_1,t_2 $ 合并为 $ t_{1,2} $ 之后,语料库的对数似然的增量最大化。来自
Hugging Face
上的例子:假设在
pre-tokenization
之后,我们得到了如下的单词及其频次的集合:xxxxxxxxxx
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)将所有单词拆分到字符,则我们得到:
xxxxxxxxxx
("h" "##u" "##g", 10), ("p" "##u" "##g", 5), ("p" "##u" "##n", 12), ("b" "##u" "##n", 4), ("h" "##u" "##g" "##s", 5)注意:
WordPiece
通过添加前缀(在BERT
中是##
)来识别子词,这可以识别一个子词是否是单词的开始。这里通过将前缀添加到单词内的每个字符来拆分的,单词的首字符不添加前缀。此时的
base vocabulary
为:xxxxxxxxxx
["b", "h", "p", "##g", "##n", "##s", "##u"]然后,
WordPiece
计算每个可能的symbol pair
,然后挑选score
最高的symbol pair
。学到的第一个
merge
是("##g", "##s") -> ("##gs")
。注意,当我们合并时,我们删除了两个token
之间的##
,所以我们添加"##gs"
到词表中。此时单词及其频次的集合为:
xxxxxxxxxx
("h" "##u" "##g", 10), ("p" "##u" "##g", 5), ("p" "##u" "##n", 12), ("b" "##u" "##n", 4), ("h" "##u" "##gs", 5)此时
base vocabulary
为:xxxxxxxxxx
["b", "h", "p", "##g", "##n", "##s", "##u", "##gs"]我们继续这样处理,直到达到我们所需的词汇量。
tokenization
算法:WordPiece
和BPE
中的tokenization
的不同在于:WordPiece
仅保存最终词表,而不保存学到的merge rule
。在应用时,从待
tokenized
的单词开始,WordPiece
找到词表中能够匹配到的最长的子词,然后对单词进行拆分。例如,如果我们使用上面例子中学到的词表来tokenize
单词"hugs"
:- 首先,单词从头开始能匹配到的词表中的最长子词是
"hug"
,所以我们在那里拆分并得到["hug", "##s"]
。 - 然后,我们继续匹配剩下的
"##s"
。刚好能够匹配到词表中的子词"##s"
。
最终,
"hugs"
的tokenization
是["hug", "##s"]
。如果使用
BPE
, 我们将按顺序应用学习到的merge rule
,并将其tokenize
为["hu", "##gs"]
,所以编码不同。- 首先,单词从头开始能匹配到的词表中的最长子词是
当
tokenization
无法在词表中找到子词时,整个单词被tokenize
为unknown
。 例如"bum"
,由于"##m"
不在词表中,由此产生的tokenization
将只是["[UNK]"]
, 不是["b", "##u", "[UNK]"]
。这是与
BPE
的另一个区别:BPE
只会将不在词汇表中的单个字符tokenize
为unknown
。 例如"bum"
,由于"##m"
不在词表中,由此产生的tokenization
是["b", "##u", "[UNK]"]
。
1.3 SentencePiece
SentencePiece
(《Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates》(2018)
)中经常使用Unigram
算法。Unigram
算法假设每个子词都是独立出现的,因此一个子词序列 $ \mathbf x = (x_1,\cdots,x_M) $ 出现的概率是每个子词出现概率的乘积,即:其中:
$ x $ 为子词, $ p(x) $ 为子词出现的概率, $ \mathcal V $ 为词表。对于给定的句子
$ X $ ,其最佳tokenization
为:其中:
$ S(X) $ 为句子 $ X $ 的所有候选tokenization
。如果我们已知词表
$ \mathcal V $ 以及每个子词出现的概率 $ p(x) $ ,则 $ \mathbf x^* $ 可以通过维特比算法求解得到。现在的问题是,给定一个训练语料库
$ D $ ,如何获得词表 $ \mathcal V $ 以及每个子词出现的概率 $ p(x) $ 。Unigram
利用EM
算法来求解如下的边际似然marginal likelihood
$ \mathcal L $ :其中:
$ X^{(s)} $ 表示语料库 $ D $ 中的第 $ s $ 个句子。这里
Unigram
将 $ p(x) $ 视作隐变量。为求解
$ \mathcal L $ ,Unigram
采用了迭代式算法:首先,启发式地从训练语料库中获取一个足够大的
seed vocabulary
。一种选择方法是:使用所有字符、以及语料库中最高频的
substring
。重复以下步骤,直到词表规模
$ |\mathcal V| $ 达到预期的值:- 固定词表,通过
EM
算法优化 $ p(x) $ 。 - 对每个子词
$ x_i $ 计算 $ \text{loss}_i $ ,其中 $ \text{loss}_i $ 表示当 $ x_i $ 从当前词表移除时,似然 $ \mathcal L $ 降低的数值。 - 根据
$ \text{loss}_i $ 进行降序排列,保留top
$ \eta\% $ 的子词(例如,80%
)。
注意,我们总是在词表中保留单个
character
从而防止out-of-vocabulary
。- 固定词表,通过
最终的词表
$ \mathcal V $ 包含了语料库中的所有单个字符、也包括了一些character-based tokenization
结果、甚至包括一些word-based tokenization
结果。因此Unigram
算法是这三者的混合体。来自
Hugging Face
上的例子:假设在
pre-tokenization
之后,我们得到了如下的单词及其频次的集合:xxxxxxxxxx
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)seed vocabulary
采用初始词表的所有严格子字符串(即,不包含它自身):xxxxxxxxxx
["h", "u", "g", "hu", "ug", "p", "pu", "n", "un", "b", "bu", "s", "hug", "gs", "ugs"]对于每个单词,考虑
tokenization
概率最高的。例如,对于"pug"
:tokenization
为["p", "u", "g"]
的概率为:这里
210
为词表中所有token
的频次之和。tokenization
为["pu", "g"]
的概率为:
Unigram
选择对单词进行tokenization
最高的那个:xxxxxxxxxx
["p", "u", "g"] : 0.000389 ["p", "ug"] : 0.0022676 ["pu", "g"] : 0.0022676所以,
"pug"
将被标记为["p", "ug"]
或者["pu", "g"]
,取决于首先遇到这些 中的哪一个。注意,在更大的语料库中这样的相等的情况很少见。通常在语料库中找到所有可能的
tokenization
并计算它们的概率,一般来说会有点困难。因此需要利用维特比算法。这里我们得到每个单词的最佳
tokenization
:xxxxxxxxxx
"hug": ["hug"] (score 0.071428) "pug": ["pu", "g"] (score 0.007710) "pun": ["pu", "n"] (score 0.006168) "bun": ["bu", "n"] (score 0.001451) "hugs": ["hug", "s"] (score 0.001701)现在我们需要计算从词表中删除每个
token
如何影响损失。然后我们根据这个损失对token
进行排序,选择top
$ \eta\% $ 的token
。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论