Bert 論文閱讀筆記

主要內容

  • Abstract
  • Introduction
  • Related Work
  • Bert
  • Experiments
  • Ablation Studies
  • Conclusion

參考論文:

《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》

正文

Abstract

這篇論文介紹一個新的語言表達模型BERT(Bidirectional Encoder Representations from Transformers)。BERT 是用于語言理解的預訓練深度雙向編碼表征的 transformer結構。它被設計為通過在所有網絡層中基于左右文本來預訓練深度雙向表征。因此通過外接一個輸出層來 fine-tuned 預訓練好的BERT 表征形成一個新的模型,這種做法可以將BERT運用在大量的其他任務上,例如問題回答任務、語言推理任務等。

Bert模型易理解且功能強大,它在11個NLP任務中都表現的最好,在機器閱讀理解SQuAD1.1跑出的成績,在兩個指標上全面超越人類。GLUE基準80.04%(7.6%絕對提升),MultiNLI準確率86.7%(5.6%絕對提升)。

一、Introduction

語言模型的預訓練對于改善許多自然語言處理任務是有效的。這些任務包括句子級別的任務像自然語言推理(Bowman等人(2015);Williams等人(2018)),和釋義。句子級任務目的是通過對句子的整體分析來預測句子之間的關系。

目前存在的將預訓練好的語言表征運用在下游任務的方法主要有:基于特征(feature-based)的和微調(fine-tuning)。基于特征的方法,比如ELMo,將預訓練好的表征作為額外的特征加到某個基于任務的架構中。基于微調的方法,比如 OpenAI GPT,引入最小任務相關的參數,運用下游的特定任務來微調訓練好的參數。這兩種方法在訓練前都有相同的目標函數,即使用單向語言模型來學習一般的語言表征。目前的這些方法限制了預訓練模型的能力特別是基于微調的方法。最主要的限制在于傳統的語言模型都是單向的,這種設計限制了訓練時模型結構的選擇。例如,OpenAI GPT 使用了一種從左向右的架構,在Transformers 的 self-attention layer 中每個分詞只能被添加到它前一個分詞之后。這種設計對于處理句子級的任務來說是個 sub-optimal,但是在分詞層面的任務中微調訓練好的模型時,這種設計可能帶來災難性的結果,因為在這類任務中,從兩個方向合并上下文是至關重要的。

作者引入了 BERT通過提出了一個新的預訓練目標:“masked language model”(MLM)。遮蔽語言模型隨機地遮蔽輸入中的一些分詞,目標是為了能夠在僅基于上下文的情況下預測出被遮蔽的分詞的id。不同于以往的從左至右的預訓練語言模型,MLM模型允許融合左邊和右邊兩邊的上下文,從而可以形成深度雙向的Transformer。同時文章引入了預測下一個句子的任務來預訓練文本對(text-pair)表征。

這篇文章的貢獻:

  • 證實了雙向預訓練對于語言表征的重要性
  • 證實了預訓練表征能夠減少了許多高度工程化的特定任務特征架構的需求(啥意思)
  • BERT 在11項自然語言處理任務中取得了最先進的效果,bert的實現代碼:https://github.com/google-research/bert.

二、Related Work

語言表征的預訓練由來已久,以下簡要回顧了最廣泛使用的方法。

2.1 Unsupervised Feature-based Approaches

預訓練的詞嵌入方法是NLP系統的組成部分,與從零開始訓練的方法相比,與訓練方法有更好的表現。為了預訓練單詞嵌入向量,Mnih和Hinton等人(2009)使用了從左到右的語言建模目標,Mikolov等人(2013)的模型在左右上下文中區分正確和錯誤單詞。

這些方法已經推廣到更廣的粒度,例如句子級的嵌入或者段落級嵌入。為了訓練句子表示,先前的工作通過訓練目標為‘對候選的下一個句子進行排序’的模型獲得(Jernite等人(2017)Logeswaran和Lee(2018)),從左到右生成下一個句子單詞以表示前一個句子(Kiros等人(2015)),或去噪自編碼器派生的目標(Hill等人(2016))。

ELMo及其前身(Peters等人(20172018a))從不同的維度概括了傳統的單詞嵌入研究。它們從左到右和從右到左的語言模型中提取上下文相關的特征。每個詞的上下文表示是從左到右和從右到左表示的連接。當將上下文單詞嵌入與現有的特定任務架構相結合時,ELMo提出幾個主要NLP基準(Peters等人(2018a))的最新技術,包括問答Rajpurkar等人(2016)、情感分析Socher等人(2013)和命名實體識別Tjong等人(2003)Melamud等人(2016)建議通過一項任務學習語境表征,使用LSTMs從左右語境預測單個單詞。與ELMo相似,它們的模型是基于特征的,并且沒有深度的雙向性。Fedus等人(2018)表明完形填空任務可以用來提高文本生成模型的健壯性。

2.2 Unsupervised Fine-tuning Approaches

與基于特征的方法一樣,第一種方法是在這個方向上只從未標記的文本中預訓練單詞嵌入參數。
最近,產生上下文詞級表示的句子或文檔編碼器已經從未標記的文本中進行了預訓練,并針對有監督的下游任務進行了微調。這些方法的優點是幾乎不需要從頭學習參數。至少在一定程度上是由于這個優勢,OpenAI-GPT在GLUE基準測試的許多句子級任務上取得了先前最先進的結果。

Figure 1.jpg

Figure 1: Overall pre-training and fine-tuning procedures for BERT. Apart from output layers, the same architectures are used in both pre-training and fine-tuning. The same pre-trained model parameters are used to initialize models for different down-stream tasks. During fine-tuning, all parameters are fine-tuned. [CLS] is a special symbol added in front of every input example, and [SEP] is a special separator token (e.g. separating questions/answers).

2.3 Transfer Learning from Supervised Data

也有研究顯示,在大數據集的監督任務中,如自然語言推理和機器翻譯,可以有效地進行轉換.計算機視覺研究也證明了從大的預先訓練的模型中轉移學習的重要性,其中一個有效的方法是用ImageNet對預先訓練的模型進行微調。

三、Bert

BERT架構中有兩個步驟:預訓練(pre-training)和微調(fine-tuning)。在預訓練階段,BERT模型在不同的預訓練任務中對未標記數據進行訓練。對于微調階段,首先使用預先訓練的參數初始化BERT模型,然后使用來自下游任務的標記數據對所有參數進行微調整。每個下游任務都有單獨的微調模型,即使它們是用相同的預訓練參數初始化的。

BERT的一個顯著特點是其在不同任務中的統一架構。預訓練的架構和最終的下游任務的架構之間的差別很小。

BERT的模型結構是基于Vaswani等人(2017)實現的多層雙向變壓器編碼器,該模型已經發布在tensor2tensor庫中。

BERT的參數說明:L表示層數(Transformer block 的數量),H表示隱藏層的數量,A表示self-attention heads 的數量。主要的兩個模型的大小分別為:

  • BERT_{BASE}(L=12,H=768,A=12,Total Parameters=110M)
  • BERT_{LARGE}(L=24,H=1024,A=16,Total Parameters=340M)

為了進行比較,作者選擇了與OpenAI GPT具有相同模型大小的BERT_{BASE}。BERT Transformer使用雙向self-attention,而GPT Transformer使用約束的self-attention,其中每個詞只能關注其左側的上下文。

為了使BERT能夠處理各種下游任務,BERT的輸入能夠在一個詞序列中明確地表示一個句子和一對句子(如\langle Question,Answeri \rangle)。句子可以是文章中的任意片段。“sequence”是指輸入到BERT的詞序列,它可以是一個句子,也可以是打包在一起的兩個句子。

作者使用了具有30000個詞的詞匯表進行WordPice (武永輝等人2016)詞嵌入。每個序列的第一個詞總是一個特殊的分類標記([CLS])。與此標記對應的最終隱藏狀態用作分類任務的聚合序列表示。句子對被打包成一個序列,有兩種方法可以區分句子。第一種是用一個標記詞([SEP])來劃分這個句子對,第二種是增加一個可學習的嵌入到每個詞中,用于區分該詞屬于句子A還是句子B。如Figure 1所示,E表示輸入嵌入,C \in\mathbb{R}^H表示[CLS]標記詞的最終隱藏向量,第i個輸入詞的最終隱藏向量表示為T_i \in \mathbb{R}^H

對于給定的詞,其輸入表示是通過對相應的詞、片段和位置嵌入求和來構造的。這種構造的可視化如Figure 2所示。

Figure 2.jpg

Figure 2: BERT input representation. The input embeddings are the sum of the token embeddings, the segmentation embeddings and the position embeddings.

3.1 Pre-training BERT

<strong>Task #1: Masked LM</strong> 作者認為深度雙向模型比從左到右模型或從左到右模型和從右到左模型的淺層連接更強大。傳統的模型都是從左到右或者從右到左訓練,這極大地限制了模型的能力。在多層的雙向訓練中會出現“標簽泄漏(since bidirectional conditioning would allow each word to indirectly “see itself”),作者提出 Masked LM 方法。對輸入的句子隨機地 Mask 住 15%的 分詞,訓練模型去預測句子中被 Mask的分詞。被 Mask的分詞對應的最后的向量會被傳入到輸出的 Softmax函數。

這種方法雖然可以得到雙向的預訓練模型,但是也存在兩個問題。

第一個就是 pre-training 和 fine-tunning 語料不匹配的問題,因為 被 Mask住的分詞不會在 fine-tunning階段出現。為了解決這個問題,被隨機挑選出來被 Mask 的分詞比不總是以 [MASK]出現。

  • 80%的時間,用 [MASK]代替被選中的詞,如 my dog is hairy -> my dog is [MASK]
  • 10%的時間,用一個隨機挑選的詞代替被選中的詞,如 my dog is hairy -> my dog is apple
  • 10%的時間,保持原來的單詞不變,如 my dog is hairy -> my dog is hairy

Transformer解碼器不知道哪個單詞需要被預測以及哪個單詞是被替換了的,因此它被要求保持對每個輸入token分布式的表征,否則會一直記著被 Mask的詞是 hairy。

第二個問題就是因為每個Batch中只有15%的分詞被預測,所以模型需要訓練更多的次數才能收斂。但是模型帶來的性能提升比計算消耗更值得。

Task #2: Next Sentence Prediction (NSP) 許多自然語言處理的任務如QA、NLI,是基于模型對兩個不同文本之間關系的理解的,而語言模型并不能直接反應這種關系。為了使預訓練模型能夠很好地處理這類任務,作者提出了 next sentence prediction 任務。特別地,在訓練集中,有50%的句子B是句子A的真正的下一句(labeled as IsNext),而另外50%的句子B是從語料中隨機抽取的句子(labeled as NotNext)。實驗結果表明,增加的這個任務在 QA 和 NLI 都取得了很好的效果。
Input=[CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
LABEL=IsNext
Input=[CLS] the man went to [MASK] store [SEP] penguin [MASK] are flight ##less birds [SEP]
LABEL=NotNext
Pre-training data 預訓練過程中使用的語料是 BooksCorpus (800M 詞) 和 English Wikipedia (2,500M 詞).

3.2 Fine-tuning BERT

Transformer中的self-attention機制允許BERT通過調整適當的輸入和輸出,對許多下游任務進行建模,無論這些任務涉及單個文本還是文本對。
對于每個任務,只需將特定于任務的輸入和輸出插入到BERT中,并對所有參數進行端到端的微調。在輸入部分,在預訓練階段的句子A和句子B類似于(1)在段落中的句子對,(2)蘊含中的前提-假設對,(3)問題回答任務中的問題-文章對,(4)文本分類中的text-?對。在輸出部分,詞級表示被輸入到詞級任務的輸出層,例如序列標記或問題回答,[CLS]表示被輸入到分類的輸出層,例如蘊涵或情感分析。

四、Experiments

本節將介紹11個NLP任務的BERT微調結果。
GLUE(The General Language Understanding Evaluation)基準是多種自然語言理解的集合任務,是一個用于評估通用 NLP 模型的基準,其排行榜可以在一定程度上反映 NLP 模型性能的高低。(GLUE 基準針對的是英文任務)。
對于GLUE的微調,輸入序列如上文所描述的一樣(單個句子或者句子對),用隱藏向量C \in \mathbb{R}^H做為標記詞([CLS])的輸出的聚合表示。在微調階段新引進來的參數僅有分類層的權重W \in \mathbb{R}^{K \times H},其中K是label的數量。使用CW來計算分類loss,例如log(softmax(CW^T)

Table 1.jpg

Table 1: GLUE Test results, scored by the evaluation server (https://gluebenchmark.com/leaderboard).
The number below each task denotes the number of training examples. The “Average” column is slightly different
than the official GLUE score, since we exclude the problematic WNLI set.8 BERT and OpenAI GPT are singlemodel, single task. F1 scores are reported for QQP and MRPC, Spearman correlations are reported for STS-B, and
accuracy scores are reported for the other tasks. We exclude entries that use BERT as one of their components.

作者設置batch_size=32,epochs=3,并對表格中的GLUE任務的數據進行微調。對于每個任務,在開發集中選擇了(5e-5,4e-5,3e-5,2e-5中)最優的學習率。

結果如Table 1所示,BERT_{BASE}Bert_{Large}在所有任務上的性能都大大優于所有模型,分別比現有最高水準的模型提高了4.5%和7.0%的平均精度。注意,除了attention masking之外,BERT_{BASE}和OpenAI GPT在模型架構方面幾乎是相同的。對于GLUE任務中最大的以及引用最廣的任務MNLI,BERT在絕對精度上提高了4.6%,我們發現Bert_{Lrage}在所有任務中都明顯優于BERT_{BASE},尤其是那些訓練數據很少的任務。

4.2 SQuAD v1.1

斯坦福問答數據集(SQuAD v1.1)包含10萬個問答對。該任務在給定問題和包含答案的文章下去預測這篇文章的答案文本片段。

對于問答任務,作者將問題和文章打包成序列做為輸入,在微調階段,僅引進開始向量S \in \mathbb{R}^H和 結束向量E \in \mathbb{R}^H。單詞i是答案片段的開始單詞的概率P_i=\frac{e^{S \cdot T_i}}{\sum_{j}e^{S \cdot T_j}}。計算答案片段的末尾單詞同樣可以用這個公式。從ij的候選答案片段的得分定義為S\cdot T_i + E\cdot T_j,其中j \geq i

Table 2展示了問答任務中的排名前幾位的模型,因此,作者使用適度的數據增強,首先對TriviaQA進行微調,然后再對SQuAD進行微調。 BERT在集成度上比排名第一的系統高出+1.5f1,在單個系統上比排名第一的系統高出+1.3f1。

Table 2.jpg

Table 2: SQuAD 1.1 results. The BERT ensemble is 7x systems which use different pre-training checkpoints and fine-tuning seeds.

Table 3.jpg

Table 3: SQuAD 2.0 results. We exclude entries that use BERT as one of their components.

4.3 SQuAD v2.0

SQuAD2.0任務擴展了SQuAD1.1問題的定義,允許在提供的段落中不存在短答案的可能性,從而使問題更加符合現實。

對于這個2.0任務,作者使用一個簡單的方法來擴展SQuAD1.1中的Bert模型。作者將那些沒有答案的問題視為有答案,且答案的開始和結束都在[CLS]標記處<font color="red">(這里理解不知道對不對)</font>,在預測時,無答案的片段得分計算為:S_{null}=S\cdot C+E\cdot C,對于最好的非空片段S_{\hat{i},j}=max_{j\geq i}S\cdot T_i+E\cdot T_j,當S_{\hat{i},j}\gt S_{null}+\pi,可以預測該問題是有答案的,其中,閾值\pi是在開發集中最大的F1值。

Table 4.jpg

Table 4: SWAG Dev and Test accuracies. ?Human performance is measured with 100 samples, as reported in
the SWAG paper.

在SQuAD2.0任務中,BERT比之前最好的模型改進了5.1個F1分數。

4.4 SWAG

Bert_{Large}的性能比基線ESIM+ELMo系統高出27.1%,OpenAI GPT高出8.3%。

五、Ablation Studies

作者對BERT的許多組件進行消除實驗,以便更好地理解它們的重要性。


Table 5.jpg

Table 5: Ablation over the pre-training tasks using the BERTBASE architecture. “No NSP” is trained without the next sentence prediction task. “LTR & No NSP” is trained as a left-to-right LM without the next sentence prediction, like OpenAI GPT. “+ BiLSTM” adds a randomly initialized BiLSTM on top of the “LTR + No NSP” model during fine-tuning.

5.1 Effect of Pre-training Tasks

通過使用與BERT_{BASE}完全相同的訓練前數據、微調方案和超參數評估兩個訓練前目標,作者證明了BERT的深度雙向性的重要性:

No NSP:雙向性模型使用MLM(masked LM)進行訓練,在NSP(next sentence prediction)任務中是沒有部分的。

LTR & No NSP:left-context-only模型使用標準的自左向右的LM進行訓練,而不用MLM。在微調時也應用了left-only約束,因為刪除它會導致預訓練/微調不匹配,從而降低下游性能。

在Table 5中可以看出,移除NSP會顯著影響QNLI,MNLI和SQuAD1.1的性能。作者通過比較“No NSP”和“ LTR&No NSP”來評估訓練的雙向性表示的影響。LTR模式在所有任務上的表現都比MLM模型差,在MRPC和SQuAD上的性能都有很大的下降。

對于SQuAD而言,顯LTR模型在單詞預測方面表現不佳,因為詞級級隱藏狀態沒有右側文本內容。為了強化LTR系統,作者隨機地在頂部初始化BiLSTM。這確實改善了SQuAD的結果,但是仍然遠不如那些預訓練的雙向模型。BiLSTM會影響GLURE任務的性能。

雖然可以訓練單獨的LTR和RTL模型,并像ELMo那樣將每個單詞表示為兩個模型的連接。但是會有如下弊端:

  • a)效率是單個雙向模型1/2;
  • b)對于QA這樣的任務來說,這是不直觀的,因為RTL模型無法對問題的答案進行限定;
  • c)這比深度雙向模型的功能要弱得多,因為它可以在每一層同時使用左上下文和右上下文。

5.2 Effect of Model Size

在本節中探討模型大小對微調任務精度的影響。作者訓練了許多具有不同層數、隱藏單元和注意頭的BERT模型,而在其他方面則使用與前面描述的相同的超參數和訓練過程。

所選的GLUE任務的結果如Table 6所示。我們可以看到,更大的模型導致所有四個數據集的精確性得到了一定的提高,即使對于只有3600個詞的訓練例子的MRPC,也與預訓練任務有很大的不同。


Table 6.jpg

Table 6: Ablation over BERT model size. #L = the number of layers; #H = hidden size; #A = number of attention heads. “LM (ppl)” is the masked LM perplexity of held-out training data.

5.3 Feature-based Approach with BERT

到目前為止,所有的BERT結果都使用了微調方法,即在預先訓練的模型中添加一個簡單的分類層,并在下游任務中聯合微調所有參數。然而,基于特征的方法從預訓練模型中提取固定特征具有一定的優勢。首先,并不是所有的任務都可以很容易地用一個Transformer-encoder架構來表示,因此需要添加一個特定于任務的模型架構。其次,預先計算一次昂貴的訓練數據表示,然后在這種表示的基礎上使用更便宜的模型運行許多實驗,這有很大的計算優勢。


Table 7.jpg

Table 7: CoNLL-2003 Named Entity Recognition results. Hyperparameters were selected using the Dev set. The reported Dev and Test scores are averaged over 5 random restarts using those hyperparameters.

為了消除這種微調方法,作者采用基于特征的方法,從一個或多個層中提取激活信息,而不需要微調BERT的任何參數。這些上下文嵌入用作在分類層之前隨機初始化的兩層768維BiLSTM的輸入,結果見Table 7。性能最好的方法是將預先訓練好的轉換器的前四個隱藏層中的詞表示連接起來,這只比微調整個模型落后0.3個f1。這表明BERT對于精細調整和基于特征的方法都是有效的。

Conclusion

近年來,基于語言模型的遷移學習(transfer)的實證研究表明,豐富的、無監督的預訓練是許多語言理解系統的一個組成部分。特別是,這些結果使得即使是低資源任務也能從深度單向架構中獲益。本文的主要貢獻是將這些發現進一步推廣到深層雙向架構中,使相同的預訓練模型能夠成功地處理一系列NLP任務。

本文作者:吳明耀
本文鏈接:https://wumingyao.github.io/2020/04/16/Pre-training-of-Deep-Bidirectional-Transformers-for-Language-Understanding/
簡書:Anunnaki
CSDN: 吳明耀の博客

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容