Présentation des modèles de pré-formation PNL: de word2vec, ELMo à BERT

Annuaire

 

Préface

word2vec

Le modèle

Échantillonnage négatif

niveau char et contexte

ELMo

BERT

Encodage bidirectionnel profond

Apprendre la représentation des relations entre les phrases et les paires de phrases

Interface de tâche en aval simple et excessive


Préface

Rappelons que dans le domaine de la compréhension de la lecture machine il n'y a pas longtemps, Microsoft et Ali ont dépassé les humains sur SQuAD avec R-Net + et SLQA, respectivement, et Baidu a dépassé les humains sur MS MARCO avec domination V-Net et BLEU. On peut dire que ces réseaux sont plus compliqués qu'un seul, et il semble que «comment concevoir un réseau plus spécifique au travail» est devenu la direction de recherche politiquement correcte dans le domaine de la PNL. Dans ce genre de vent, peu importe word2vec, gant ou fasttext, il ne peut que servir de cerise sur le gâteau. Qu'en est-il de l'apprentissage par transfert et de la pré-formation? Il semble que la PNL n'ait jamais été le protagoniste.
Xiao Xi avait un peu honte quand il a écrit cet article. Après une longue période de présentation et de migration, bien qu'il ait intuitivement pensé que cela devrait être le problème central de la PNL, il n'a pas fait de résultats expérimentaux qui lui étaient satisfaisants. La veille de la sortie du BERT, j'ai senti que la pauvreté restreignait mon imagination ╮ ( ̄ ▽  ̄ ””) ╭ (barré), et je sentais que mon point de vue était encore trop étroit. Tout le monde a une compréhension différente du BERT. Cet article va essayer de parler du BERT du point de vue de word2vec et ELMo. Ce qui suit est un bref aperçu de l'essence de word2vec et ELMo. Ceux qui ont très bien compris peuvent rapidement passer au chapitre BERT.

word2vec

En parlant de ce sont toutes des phrases clichées que je voudrais écrire encore et encore. Dès que word2vec de Google est sorti en 2013, tous les domaines de la PNL se sont épanouis. Il semblait que j'étais gêné d'écrire un article sans utiliser de vecteurs de mots pré-formés. Qu'est-ce que word2vec?

Le modèle

C'est évidemment un modèle de langage "linéaire". Puisque notre objectif est d'apprendre des vecteurs de mots, et que les vecteurs de mots doivent prendre en charge sémantiquement certaines "opérations sémantiques linéaires", telles que "Empereur-Reine = Homme-Femme" (en ignorant Wu Zetian), alors un modèle linéaire est naturellement suffisant, fonctionnant C'est très rapide et capable de terminer la tâche, très élégant.

De plus, l'un des éléments essentiels de word2vec est d'optimiser l'ensemble des méthodes d'accélération softmax du modèle de langage, et de remplacer les méthodes hiérarchiques traditionnelles softmax et NCE par une méthode "d'échantillonnage négatif" apparemment ouverte. Et en quoi consiste exactement "échantillonnage négatif" dans ce nom?

Échantillonnage négatif

Nous savons que pour les modèles de langage d'apprentissage, la couche softmax est très difficile à calculer. Après tout, ce que vous voulez prédire est le mot de la position actuelle, puis le nombre de catégories est équivalent à la taille du dictionnaire, donc le nombre de catégories est souvent de dizaines de milliers à dizaines de milliers La fonction est bien sûr très laborieuse. Cependant, si notre objectif n'est pas de former un modèle de langage précis, mais uniquement d'obtenir le sous-produit des vecteurs de mots du modèle de langage, alors nous n'avons qu'à utiliser une sous-tâche cachée qui est moins coûteuse à calculer. La. Pensez-y: est-ce particulièrement laborieux de vous donner 10 000 cartes avec des numéros et de vous permettre d'en connaître le maximum? Mais si vous extrayez la valeur maximale à l'avance et la mélangez avec cinq cartes tirées au hasard pour vous permettre de choisir la valeur maximale, est-ce plus facile? L'échantillonnage négatif est cette idée, c'est-à-dire qu'au lieu de laisser directement le modèle trouver le mot le plus probable dans tout le vocabulaire, on lui donne directement le mot (c'est-à-dire un exemple positif) et plusieurs mots de bruit échantillonnés au hasard (c'est-à-dire des exemples négatifs échantillonnés) Tant que le modèle peut trouver le mot correct à partir de cela, il est considéré que l'objectif est atteint. La fonction objective correspondant à cette idée est donc: voici un exemple positif, un exemple négatif échantillonné au hasard (k échantillons), et une fonction sigmoïde. Maximisez ensuite la probabilité d'exemples positifs et minimisez la probabilité d'exemples négatifs. Cette idée d'échantillonnage négatif a été appliquée avec succès dans le modèle BERT, mais la granularité est passée des mots aux phrases. Ne vous inquiétez pas, regardez en arrière lentement ~

niveau char et contexte

Bien que beaucoup de travail de 2015 à 2017 ait également essayé de commencer par le niveau de caractère, pour trouver une autre façon de se débarrasser des règles du jeu de vecteur de mots pré-formé, mais la mesure réelle n'est qu'un flash dans la casserole, et elle a été rapidement vaincue [8] [9]. Cependant, les gens ont également réalisé que le texte de niveau char contient également des modèles qui sont difficiles à décrire dans le texte de niveau mot. Par conséquent, d'une part, le vecteur de mot FastText [5] qui peut apprendre les caractéristiques de niveau char apparaît. Dans les tâches supervisées, nous avons commencé à introduire la représentation textuelle au niveau des caractères via CNN peu profond, HIghwayNet, RNN et d'autres réseaux. Cependant, jusqu'à présent, les vecteurs de mots sont tous hors contexte. En d'autres termes, le même mot est toujours le même vecteur de mots dans différents contextes, ce qui conduit évidemment à l'absence de désambiguïsation du sens des mots (WSD) dans le modèle de vecteur de mots. Par conséquent, afin de rendre le vecteur de mots sensible au contexte, les gens ont commencé à coder en fonction de la séquence de vecteurs de mots dans des tâches spécifiques en aval. ** Bien sûr, la méthode de codage la plus courante consiste à utiliser le réseau RNN, en plus de l'utilisation réussie de CNN profond pour coder le travail (comme la classification de texte [6], la traduction automatique [7], la compréhension de la lecture machine [4] ) Bien sûr! Et! Google a dit, CNN est trop vulgaire, nous devons utiliser un réseau entièrement connecté! (Rayer) l'attention de soi! Il existe donc un modèle Transformer [11] qui est profondément personnalisé pour la PNL. La proposition de Transformer concerne les tâches de traduction automatique, mais elle exerce également une grande puissance dans d'autres domaines tels que le dialogue de récupération [3]. Cependant, comme on constate qu'il existe fondamentalement un besoin d'encodage dans chaque tâche PNL, pourquoi ne pas laisser le mot vecteur avoir la capacité contextuelle au début? Il y a donc ELMo [2].

ELMo

Bien sûr, ELMo n'est en fait pas le premier modèle qui essaie de générer des vecteurs de mots contextuels, mais c'est en effet un modèle qui vous donne une bonne raison d'abandonner word2vec (sourire manuel). Après tout, les performances de sacrifier la vitesse d'inférence sont bien meilleures. Dans la plupart des cas, la valeur est ~ ELMo est un bi-lstm empilé sur la couche modèle (à proprement parler, deux lstm empilés unidirectionnels sont entraînés), il y a donc bien sûr une bonne capacité de codage. Dans le même temps, son implémentation de code source prend également en charge l'utilisation de Highway Net ou CNN pour introduire en outre un codage au niveau des caractères. La formation est naturellement aussi la fonction de probabilité maximale de la norme de modèle de langage, mais le point culminant de cet ELMo n'est bien sûr pas la couche modèle, mais elle montre indirectement à travers des expériences que dans le RNN multicouche, les caractéristiques apprises par différentes couches sont Il existe des différences, donc ELMo propose de définir un paramètre entraînable pour la couche de vecteur de mots d'origine et la couche cachée de chaque RNN lorsque la pré-formation est terminée et migrée vers la tâche NLP en aval. La multiplication vers la couche correspondante et la sommation joueront le rôle de pondération, puis le mot vecteur obtenu par la "somme pondérée" sera mis à l'échelle par un paramètre pour mieux s'adapter à la tâche en aval.

ps: En fait, ce dernier paramètre est toujours très important. Par exemple, dans word2vec, en général, la variance du vecteur de mots appris par cbow et sg est relativement grande. À l'heure actuelle, la variance correspond au vecteur de mots qui convient à la variance de couche suivante des tâches en aval. , Plus facile à améliorer

L'expression mathématique est la suivante,

où L = 2 est le paramètre du papier ELMo, j = 0 représente la couche de vecteur de mots d'origine, j = 1 est la première couche cachée de lstm et j = 2 est la deuxième couche cachée. C'est le résultat du paramètre normalisé par softmax (c'est-à-dire ). Grâce à cette stratégie de migration, les tâches qui nécessitent une désambiguïsation du sens des mots sont plus susceptibles de se voir attribuer un poids important à la deuxième couche masquée par le biais de la formation, tandis que les tâches qui ont des exigences évidentes pour une partie du discours et de la syntaxe peuvent avoir des paramètres pour la première couche masquée. Apprentissage d'une valeur relativement importante (conclusion expérimentale). En bref, cela vous donne un vecteur de mots qui peut être personnalisé par des tâches en aval et qui a plus de fonctionnalités.Il n'est pas surprenant que l'effet soit bien meilleur que word2vec. Mais cela dit, l'objectif d'ELMo est seulement d'apprendre des vecteurs de mots plus puissants et plus contextuels. Son but est toujours de fournir une base solide pour les tâches en aval, et cela ne signifie pas de tuer le roi.. Et nous savons qu'il ne suffit pas d'effectuer un encodage suffisant et puissant sur le texte (c'est-à-dire d'obtenir des fonctionnalités très précises et riches de chaque lexème) pour couvrir toutes les tâches PNL. Dans des tâches telles que l'AQ, la compréhension en lecture automatique (MRC), l'inférence en langage naturel (NLI) et le dialogue, il existe de nombreux modèles plus complexes qui doivent être saisis, tels que la relation entre les phrases. Pour cette raison, diverses attentions fantaisistes seront ajoutées au réseau dans les tâches en aval (voir SOTA dans NLI, MRC, Chatbot). Avec la nécessité de capturer des modèles plus magiques, les chercheurs ont personnalisé une variété de structures de réseau pour chaque tâche en aval, résultant en le même modèle, qui raccroche lorsque la tâche est légèrement modifiée, même dans le cas de la même tâche. Les modifications ultérieures d'un autre ensemble de données distribué entraîneront une perte de performances importante, ce qui n'est évidemment pas conforme au comportement linguistique humain ~ savoir que la capacité de généralisation humaine est très forte, ce qui montre que la piste de développement de l'ensemble de la PNL est peut-être erronée maintenant Oui, en particulier sous la direction de SQuAD, épuisant diverses astuces et structures sophistiquées pour brosser la liste, quelle est la signification de la PNL? Il semble que ce soit loin, mais heureusement, cette déviation de plus en plus est finalement stoppée par un modèle, à savoir les représentations d'encodeur bidirectionnel des transformateurs (BERT) [1] publié par Google il y a quelques jours .

BERT

La signification la plus importante de cet article n'est pas le modèle utilisé, ni comment le former, mais il propose une toute nouvelle règle de jeu. Avant de commencer le jeu, aidez Xiao Xi à commander quelques petites annonces, OK? \ (// ∇ //) \

Comme mentionné précédemment, il est en fait très imprudent de personnaliser profondément la structure du modèle complexe avec une capacité de généralisation extrêmement faible pour chaque tâche PNL, et cela va dans la mauvaise direction. Étant donné qu'ELMo aura une telle amélioration par rapport à word2vec, cela montre que le potentiel des modèles de pré-formation est bien plus que de fournir un vecteur de mots précis pour les tâches en aval , alors pouvons-nous pré-former directement un modèle au niveau de la quille? S'il a complètement décrit les caractéristiques du niveau de caractère, du niveau de mot, du niveau de phrase et même de la relation entre les phrases, alors dans différentes tâches PNL, il suffit de personnaliser une couche de sortie très légère pour la tâche (telle qu'une seule couche) MLP) C'est bien, après tout, le modèle de squelette est déjà fait. Et le BERT a fait exactement cela, ou plutôt, il l'a vraiment fait. En tant que modèle général au niveau de la quille, il a facilement contesté la personnalisation approfondie de 11 tâches. . . Alors, comment cela a-t-il été fait?

Encodage bidirectionnel profond

Premièrement, il souligne que le modèle pré-formé précédent n'est pas suffisant pour apprendre des vecteurs de mots sensibles au contexte! Bien que dans les tâches supervisées en aval, la méthode de codage soit déjà très remplie de cloches et de sifflets, le codage bidirectionnel profond est fondamentalement devenu la norme pour de nombreuses tâches complexes en aval (telles que MRC, dialogue) . Mais sur le modèle pré-formé, le modèle de pointe précédent est uniquement basé sur le modèle de langage traditionnel, et le modèle de langage traditionnel est unidirectionnel (défini mathématiquement) , c'est-à-dire et souvent très peu profond (imaginez le tas LSTM Au troisième étage, le train ne bouge pas, et vous devez aller à diverses astuces), comme ELMo. De plus, bien que ELMo utilise un RNN bidirectionnel pour le codage, les RNN dans ces deux directions sont réellement formés séparément, mais un simple ajout est effectué à la fin de la couche de perte. De cette façon, pour les mots dans chaque direction, les mots de l'autre côté ne peuvent pas être vus lorsqu'ils sont codés. De toute évidence, la sémantique de certains mots dans une phrase dépendra de certains mots sur les côtés gauche et droit de celle-ci, et il est impossible de décrire clairement en encodant dans une direction. ** Alors pourquoi ne pas faire un véritable codage bidirectionnel comme dans les tâches de supervision en aval? ** La raison est claire quand on y pense. Après tout, le modèle de langage traditionnel consiste à prédire le mot suivant comme objectif de formation. Cependant, si un codage bidirectionnel est effectué, cela ne signifie pas que le mot à prédire a été vu.╮ ( ̄ ▽  ̄ ””) ╭Bien sûr, une telle prédiction n'a pas de sens. Par conséquent, dans BERT, il est proposé d'utiliser une nouvelle tâche pour former le modèle qui peut vraiment coder dans les deux directions dans la tâche de supervision. Cette tâche est appelée modèle de langage masqué (LM masqué).

LM masqué

Comme son nom l'indique, Masked LM signifie qu'au lieu de donner le mot qui est déjà apparu et de prédire le mot suivant comme LM traditionnel, nous couvrons directement une partie de la phrase entière (sélectionnée au hasard) (la masquer). Vous pouvez effectuer un codage bidirectionnel en toute sécurité, puis laisser le modèle prédire en toute sécurité quels sont ces mots couverts. Cette tâche était en fait appelée le test de cloze (probablement traduit par "test de Gestalt"). Cela provoque évidemment quelques problèmes mineurs. Bien que le codage bidirectionnel puisse être assuré de cette manière, les balises couvertes sont également codées pendant le codage╮ ( ̄ ▽  ̄ "") ╭ et ces balises de masque n'existent pas dans les tâches en aval. . . Que dois-je faire? À cet égard, afin de régler le modèle pour ignorer autant que possible l'influence de ces marques, l'auteur dit au modèle "ce sont des bruits et des bruits! Peu fiables! Ignorez-les!" Pour un mot couvert:

  • Il y a 80% de chances de le remplacer par une balise "[mask]"

  • Il y a 10% de chances de le remplacer par un mot échantillonné au hasard

  • Il y a une probabilité de 10% qu'aucun remplacement ne soit effectué (bien qu'aucun remplacement ne soit effectué, il faut le prévoir)

Encodeur

Dans le choix de l'encodeur, l'auteur n'a pas utilisé le bi-lstm de la mauvaise rue, mais a utilisé l'encodeur Transformer qui peut être rendu plus profond et a un meilleur parallélisme. De cette façon, les mots dans chaque position lexicale peuvent encoder directement chaque mot dans la phrase indépendamment de la direction et de la distance. D'un autre côté, je pense subjectivement que Transformer est plus facile à protéger contre la marque de masque que lstm. Après tout, le processus d'auto-attention peut affaiblir complètement le poids correspondant de la marque de masque, mais comment la porte d'entrée dans lstm traite-t-elle la marque de masque? Alors c'est inconnu. Attendez une minute, Xiao Xi a également déclaré dans l'article précédent, en utilisant évidemment l'encodeur Transformer ne perdra évidemment pas les informations de localisation? L'auteur a-t-il ici une position de codage des fonctions sin et cos redoutée comme le papier Transformer original? Et il n'y a rien de tel, l'auteur ici est très simple et grossier pour former directement une position intégrant ╮ ( ̄ ▽  ̄ ””) ╭ C'est-à-dire, par exemple, si je tronque la phrase sur une longueur de 50, alors nous avons 50 positions, donc Il y a 50 mots qui représentent la position, de la position 0 à la position 49. . . Ensuite, donnez à chaque mot de position un vecteur de mots initialisé au hasard, puis entraînez-vous avec eux (je veux dire que ce chat spécial peut également fonctionner? C'est trop simple et grossier ...). De plus, dans la combinaison de l'incorporation de position et de l'incorporation de mots, l'addition directe est sélectionnée dans BERT. Enfin, en termes de profondeur, l'encodeur final de la version complète BERT est superposé à 24 couches de bloc d'attention multi-têtes (il faut savoir que le modèle SOTA DAM dans le dialogue n'utilise que 5 couches ...). . . Et chaque bloc contient 16 taps, 1024 unités cachées ╭ ( ̄ ▽  ̄ ””) ╭ slogan ici: l'argent est tout ce dont vous avez besoin (barré)

Apprendre la représentation des relations entre les phrases et les paires de phrases

Comme mentionné précédemment, dans de nombreuses tâches, l'encodage seul ne suffit pas pour terminer la tâche (cela apprend juste un tas de fonctionnalités au niveau du jeton), et vous devez capturer certains modèles au niveau de la phrase pour terminer SLI, QA, dialogue, etc. Représentation des phrases, interaction entre les phrases et tâches de correspondance. À cet égard, le BERT a introduit une autre tâche extrêmement importante mais extrêmement légère pour essayer d'apprendre ce modèle.

Échantillonnage négatif au niveau de la phrase

Rappelez-vous que Xiao Xi a dit dans le chapitre précédent de word2vec, que l'essence de word2vec est l'introduction d'une élégante tâche d'échantillonnage négatif pour apprendre la représentation au niveau des mots. Et si nous généralisons ce processus d'échantillonnage négatif au niveau de la phrase? C'est la clé de l'apprentissage BERT de la représentation au niveau de la phrase. BERT est similaire à word2vec ici, mais construit une tâche de classification au niveau de la phrase. Autrement dit, une phrase donnée en premier (équivalent au contexte donné dans word2vec), sa phrase suivante est un exemple positif (équivalent au mot correct dans word2vec), et une phrase est échantillonnée au hasard comme un exemple négatif (équivalent à un échantillonnage aléatoire dans word2vec Word), puis effectuez deux classifications au niveau de la phrase (c'est-à-dire, jugez si la phrase est la prochaine phrase de la phrase actuelle ou du bruit). Grâce à cette simple tâche d'échantillonnage négatif au niveau des phrases, BERT peut apprendre la représentation des phrases aussi facilement que word2vec apprend la représentation des mots.

Représentation au niveau de la phrase

Attendez, je l'ai dit depuis longtemps, mais je n'ai pas dit comment exprimer la phrase. . . Le BERT ici n'est pas comme la pratique courante dans les tâches de supervision en aval. Sur la base du codage, un regroupement global ou similaire est d'abord effectué. Il est le premier dans chaque séquence (pour la phrase à la tâche, il s'agit de deux phrases orthographiées, Pour les autres tâches, il s'agit d'une phrase) un jeton spécial est ajouté en face d'elle, et il est marqué comme [CLS], comme indiqué dans la figure

ps: [sep] ici est le séparateur entre les phrases. BERT prend également en charge l'expression des paires de phrases d'apprentissage. Ici, [SEP] est de distinguer le point de coupure des paires de phrases.

Laissez ensuite l'encodeur effectuer un codage profond sur [CLS]. La couche cachée la plus élevée de codage profond est la représentation de la phrase entière / paire de phrases. Cette approche est un peu déroutante à première vue, mais n'oubliez pas que Transformer peut coder des informations globales dans chaque position indépendamment de l'espace et de la distance, et [CLS] en tant que représentation phrase / paire de phrases suit directement la couche de sortie du classificateur Connecté, donc en tant que «niveau» sur le chemin de propagation en arrière du gradient, nous trouverons bien sûr un moyen d'apprendre les caractéristiques de niveau supérieur liées à la classification. De plus, afin de permettre au modèle de distinguer si chaque mot qu'il contient appartient à la "phrase de gauche" ou à la "phrase de droite", l'auteur introduit le concept d '"intégration de segments" pour distinguer les phrases. Pour les paires de phrases, l'incorporation A et l'incorporation B sont utilisées pour représenter respectivement les phrases gauche et droite; pour les phrases, il n'y a que l'intégration A. L'incorporation A et B sont également formés avec le modèle.

ps: cette méthode est simple et approximative comme l'intégration de position. Il est vraiment difficile de comprendre pourquoi BERT est utilisé dans la tâche de "paires de questions quora", qui nécessite théoriquement que le réseau maintienne la symétrie. Cela peut toujours fonctionner et l'ambiance est compliquée.

Donc, à la fin, la représentation de chaque jeton de BERT est formée en ajoutant le jeton de vecteur de mot d'origine incorporant le jeton, l'incorporation de position mentionnée ci-dessus et le segment d'incorporation ici, comme le montre la figure:

Interface de tâche en aval simple et excessive

Cela montre vraiment que le modèle BERT est un modèle au niveau de la quille et n'est plus un vecteur de mots. C'est sa conception d'interface avec diverses tâches en aval, ou un mot plus étranger est appelé une stratégie de migration. Tout d'abord, étant donné que les représentations de niveau supérieur des phrases et des paires de phrases sont obtenues, bien sûr, pour les tâches de classification de texte et les tâches de correspondance de texte (la correspondance de texte est en fait également une tâche de classification de texte, mais l'entrée est une paire de textes), il suffit d'utiliser Représentation (c'est-à-dire que l'encodeur est sorti en haut du lexème [CLS]) plus une couche de MLP ~ Puisque le texte est profondément encodé bidirectionnellement, alors seule la couche de sortie softmax doit être ajoutée pour les tâches d'étiquetage de séquence. Même le CRF est inutile ~ Ce qui a fait encore plus penser à Xi Xi, c'est que sur des tâches d'extraction étendues telles que SQuAD, il suffit d'enregistrer les deux packages d'encodage d'encodage profond et d'attention profonde, et même oser utiliser directement le pointeur de la couche de sortie. Net perdu? Tout comme DrQA, utilisez deux classificateurs linéaires pour afficher respectivement le début et la fin de la plage? Pas grand chose à dire, déjà agenouillé m (_ _) m Enfin, regardons l'effet expérimental.

Eh bien, c'est très Google. Dès que ce document est sorti, Xiao Xi était très heureux, car bon nombre des idées précédentes n'avaient pas besoin d'être vérifiées par des expériences, car elles ont été tuées par la classification BERT (。 ́︿ ̀。), les tâches de classification, d'annotation et de migration peuvent toutes être démarrées depuis le début, SQuAD Le plan de construction du bâtiment peut également être interrompu Merci à BERT de ne pas avoir exécuté la tâche de génération, ce qui donne un peu d'imagination aux gens. Eh bien, souriez et pleurez manuellement.

Les références

[1] 2018 | BERT- Pré-formation de transformateurs bidirectionnels profonds pour la compréhension du langage
[2] 2018NAACL | Représentations de mots contextualisées profondes
[3] ACL 2018 | Sélection de réponse multitours pour les chatbots avec un réseau de correspondance d'attention approfondie
[4] 2018ICLR | Compréhension de lecture rapide et précise en combinant auto-attention et convolution
[5] 2017TACL | Enrichissement des vecteurs de mots avec des informations de sous-mots
[6] 2017ACL | Réseaux de neurones convolutionnels à pyramide profonde pour la catégorisation de texte
[7] 2017 | Séquence convolutionnelle à apprentissage séquentiel
[8] 2017 | Les réseaux convolutionnels doivent-ils être profonds pour la classification de texte?
[9] 2016 | Réseaux de neurones convolutifs pour la catégorisation de texte / niveau de mot peu profond vs niveau de caractère profond
[10] 2013NIPS | Représentations-distribuées-de-mots-et-phrases-et-leur-compositionnalité

Publié 45 articles originaux · louange gagné 2 · Vues 5228

Je suppose que tu aimes

Origine blog.csdn.net/xixiaoyaoww/article/details/105460274
conseillé
Classement