{"notes":[{"id":"graph-learning/graphsage","category":"graph-learning","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"GraphSAGE","subtitle":"Faire l'appel par sondage","author":"Z. Yuan","paperDate":"2017-06-07","publishedOn":"2023-10-21","world":"external/graphsage","paperTitle":"Inductive Representation Learning on Large Graphs","paperUrl":"https://arxiv.org/abs/1706.02216","bibliography":{"title":"Inductive Representation Learning on Large Graphs","authors":["William L. Hamilton","Rex Ying","Jure Leskovec"],"url":"https://arxiv.org/abs/1706.02216","pdfUrl":"https://arxiv.org/pdf/1706.02216v4","codeUrl":"https://github.com/williamleif/GraphSAGE","preprint":{"id":"1706.02216","submittedOn":"2017-06-07","url":"https://arxiv.org/abs/1706.02216"},"publication":{"venue":"NeurIPS","year":2017,"kind":"conference","url":"https://papers.nips.cc/paper_files/paper/2017/hash/5dd9db5e033da9c6fb5ba83c7a7ebea9-Abstract.html"},"citation":"@misc{graphlearninggraphsage2017,\n  title = {{Inductive Representation Learning on Large Graphs}},\n  author = {William L. Hamilton and Rex Ying and Jure Leskovec},\n  year = {2017},\n  eprint = {1706.02216},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1706.02216}\n}\n","citationPath":"/content/papers/citations/graph-learning/graphsage.1a0b3fd6e8b8.bib"},"thumbnail":{"src":"/content/papers/assets/88f6d9397f20155603c7ee0daef374fb944aac5fb73ed6573a573560b5b9c6aa.png","width":1090,"height":384},"locale":"fr","path":"/content/papers/fr/graph-learning/graphsage.94d056671844.md","headings":[{"id":"poser-le-problème","text":"Poser le problème","depth":2},{"id":"transductif-et-inductif","text":"Transductif et inductif","depth":3},{"id":"trop-de-voisins","text":"Trop de voisins","depth":3},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"lalgorithme","text":"L'algorithme","depth":3},{"id":"tirer-les-voisins-au-sort","text":"Tirer les voisins au sort","depth":3},{"id":"trois-agrégateurs","text":"Trois agrégateurs","depth":3},{"id":"apprendre-sans-étiquettes","text":"Apprendre sans étiquettes","depth":3},{"id":"le-lien-avec-le-test-wl","text":"Le lien avec le test WL","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"trois-jeux-de-données","text":"Trois jeux de données","depth":3},{"id":"résultats-principaux","text":"Résultats principaux","depth":3},{"id":"le-compromis-entre-vitesse-et-échantillonnage","text":"Le compromis entre vitesse et échantillonnage","depth":3},{"id":"la-suite","text":"La suite","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"graph-learning/gat","relation":"citing","topic":""}]},{"id":"graph-learning/gat","category":"graph-learning","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"GAT","subtitle":"Tous les voisins n'ont pas le même poids","author":"Z. Yuan","paperDate":"2017-10-30","publishedOn":"2023-11-10","world":"external/gat","paperTitle":"Graph Attention Networks","paperUrl":"https://arxiv.org/abs/1710.10903","bibliography":{"title":"Graph Attention Networks","authors":["Petar Veličković","Guillem Cucurull","Arantxa Casanova","Adriana Romero","Pietro Liò","Yoshua Bengio"],"url":"https://arxiv.org/abs/1710.10903","pdfUrl":"https://arxiv.org/pdf/1710.10903v3","codeUrl":"https://github.com/PetarV-/GAT","preprint":{"id":"1710.10903","submittedOn":"2017-10-30","url":"https://arxiv.org/abs/1710.10903"},"publication":{"venue":"ICLR","year":2018,"kind":"conference","url":"https://arxiv.org/abs/1710.10903"},"citation":"@misc{graphlearninggat2017,\n  title = {{Graph Attention Networks}},\n  author = {Petar Veličković and Guillem Cucurull and Arantxa Casanova and Adriana Romero and Pietro Liò and Yoshua Bengio},\n  year = {2017},\n  eprint = {1710.10903},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1710.10903}\n}\n","citationPath":"/content/papers/citations/graph-learning/gat.402fa57986a5.bib"},"thumbnail":{"src":"/content/papers/assets/1a68144470e25ef01f2cd6ccf405483bc7960ca1cc9f7ebf5991060fb3a92010.png","width":1124,"height":540},"locale":"fr","path":"/content/papers/fr/graph-learning/gat.cb0d383f3076.md","headings":[{"id":"poser-le-problème","text":"Poser le problème","depth":2},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"une-tête-dattention","text":"Une tête d'attention","depth":3},{"id":"plusieurs-têtes","text":"Plusieurs têtes","depth":3},{"id":"coût-et-propriétés","text":"Coût et propriétés","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"protocole-expérimental","text":"Protocole expérimental","depth":3},{"id":"résultats-principaux","text":"Résultats principaux","depth":3},{"id":"ce-qui-a-été-appris","text":"Ce qui a été appris","depth":3},{"id":"les-limites-relevées-par-les-auteurs","text":"Les limites relevées par les auteurs","depth":3},{"id":"une-attention-statique","text":"Une attention statique","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"graph-learning/gcn","relation":"referenced","topic":""},{"id":"graph-learning/graphsage","relation":"referenced","topic":""}]}],"text":"De nouveaux messages arrivent chaque minute sur Reddit, de nouvelles vidéos chaque jour sur YouTube. Un système de recommandation doit calculer les représentations de ces nouveaux nœuds, idéalement tout de suite, sans réentraîner le graphe entier.\n\nAvant 2017, les principales méthodes de plongement de nœuds en sont incapables. DeepWalk et node2vec apprennent un vecteur par nœud, comme dans une table où les nouveaux venus n'ont aucune entrée. GCN absorbe bien les caractéristiques des nœuds, mais son article entraîne tout le graphe ensemble et charge la matrice d'adjacence entière à chaque pas.\n\nWilliam Hamilton, Rex Ying et Jure Leskovec, de Stanford, changent la cible de l'apprentissage. Ils apprennent une fonction qui calcule un vecteur depuis les voisins. Une fois apprise, elle s'applique directement à tout nouveau nœud doté de caractéristiques et de voisins.\n\n## Poser le problème\n\n### Transductif et inductif\n\nL'article distingue deux situations.\n\nEn **transductif**, tout le graphe est visible à l'entraînement, mais certains nœuds sont sans étiquette : c'est la classification semi-supervisée de l'article GCN. En **inductif**, de nouveaux nœuds, voire des graphes entiers, apparaissent après l'entraînement.\n\nLes auteurs jugent l'inductif plus difficile. Le modèle doit apprendre à reconnaître le rôle d'un nœud à partir de sa structure locale et de ses caractéristiques, au-delà de la mémorisation de sa position ; il doit aussi placer les nouveaux nœuds dans le même espace que les anciens, sans les avoir vus à l'entraînement.\n\nLa plupart des plongements existants sont transductifs. Pour intégrer de nouveaux nœuds, ils doivent relancer plusieurs tours d'optimisation au test, ce qui est lent.\n\n### Trop de voisins\n\nLe deuxième problème est l'échelle. Le jeu Reddit compte 232,965 messages ; deux messages sont reliés si un même utilisateur les a commentés. Chaque message a en moyenne 492 arêtes.\n\nSi chaque nœud regarde tous ses voisins à deux sauts, un seul peut mobiliser des centaines de milliers de nœuds. La mémoire et le temps par lot deviennent imprévisibles.\n\n## Résoudre le problème\n\n### L'algorithme\n\nGraphSAGE vient de SAmple and aggreGatE, échantillonner et agréger. La propagation avant comporte $K$ tours, chacun effectuant trois opérations pour chaque nœud $v$ :\n\n$$\nh^k_{\\mathcal N(v)}=\\mathrm{AGGREGATE}_k\\left(\\left\\{h^{k-1}_u,\\ \\forall u\\in\\mathcal N(v)\\right\\}\\right)\n$$\n\n$$\nh^k_v=\\sigma\\left(W^k\\cdot\\mathrm{CONCAT}\\left(h^{k-1}_v,\\ h^k_{\\mathcal N(v)}\\right)\\right)\n$$\n\n$$\nh^k_v\\leftarrow h^k_v/\\left\\|h^k_v\\right\\|_2\n$$\n\nOn agrège d'abord les représentations des voisins en un vecteur, puis on le **concatène** avec la représentation du nœud au tour précédent. On multiplie par la matrice de poids, applique la non-linéarité, puis normalise en L2. $h^0_v$ est l'entrée ; la sortie du tour $K$ est le plongement du nœud.\n\nLa concaténation est la grande différence avec GCN. GCN traite le nœud comme un voisin parmi d'autres, les moyenne ensemble et partage le même $W$. GraphSAGE sépare le nœud de ses voisins, ce qui leur attribue deux jeux de poids. Les auteurs y voient une connexion de saut entre profondeurs différentes, qui améliore nettement les expériences.\n\n[![Figure 1 de l'article : trois étapes de gauche à droite. On échantillonne d'abord les voisins à un et deux sauts autour du nœud cible ; un agrégateur rapporte ensuite leurs caractéristiques vers ce nœud ; la représentation obtenue prédit enfin le contexte du graphe et les étiquettes.](/content/papers/assets/88f6d9397f20155603c7ee0daef374fb944aac5fb73ed6573a573560b5b9c6aa.png)](/content/papers/assets/88f6d9397f20155603c7ee0daef374fb944aac5fb73ed6573a573560b5b9c6aa.png)\n\n*Figure 1 de l'article (Hamilton et al.), extraite de la [**page 2 du PDF**](https://arxiv.org/pdf/1706.02216v4#page=2). Légende originale omise.*\n\n### Tirer les voisins au sort\n\n$\\mathcal N(v)$ est un **ensemble de taille fixe de voisins tirés uniformément**, renouvelé à chaque tour. Avec $S_i$ voisins au tour $i$, le coût d'un lot est borné par $O\\left(\\prod_{i=1}^KS_i\\right)$. Les auteurs obtiennent de bons résultats avec $K=2$ et $S_1\\cdot S_2\\le500$ ; ils utilisent $S_1=25$ et $S_2=10$.\n\nCalculons l'écart à partir du degré moyen de Reddit :\n\n```python\nS1, S2 = 25, 10                 # 25 voisins au premier niveau, puis 10 pour chacun au deuxième\navg_deg = 492                   # Degré moyen sur Reddit\nprint(\"Avec échantillonnage, au plus:\", 1 + S1 + S1 * S2, \"nœuds par cible\")\nprint(\"Sans échantillonnage, à deux sauts au plus:     \", 1 + avg_deg + avg_deg ** 2, \"nœuds\")\n```\n\n```text\nAvec échantillonnage, au plus: 276 nœuds par cible\nSans échantillonnage, à deux sauts au plus:      242557 nœuds\n```\n\nLe deuxième nombre est une borne grossière qui ne retire pas les voisins répétés, mais il dépasse déjà les 232,965 nœuds du jeu entier. Sans échantillonnage, calculer la représentation à deux couches d'un nœud revient presque à lire tout le graphe.\n\nEn mini-lots, les auteurs échantillonnent d'abord vers l'extérieur, depuis les nœuds cibles, tous les voisins requis. Ils calculent ensuite de l'extérieur vers l'intérieur, couche par couche, uniquement les nœuds effectivement utilisés par la récurrence.\n\nParcourons une couche sur un petit graphe à six nœuds, avec 2 voisins tirés par nœud et une agrégation par moyenne :\n\n```python\nimport numpy as np\nnp.set_printoptions(precision=2, suppress=True)\nrng = np.random.default_rng(0)\n\nneighbors = [[1, 2], [0, 2, 3], [0, 1, 3, 4, 5], [1, 2], [2], [2]]\nh = rng.random((6, 3))                       # 6 nœuds, 3 caractéristiques chacun\nW = rng.normal(size=(4, 6))                  # 6 dimensions concaténées → 4 dimensions en sortie\n\ndef sage_layer(h, neighbors, W, S):\n    out = []\n    for v, nbrs in enumerate(neighbors):\n        picked = rng.choice(nbrs, size=S, replace=len(nbrs) < S)   # Avec remise si les voisins sont trop peu nombreux\n        h_nb = h[picked].mean(0)                                    # Agrégation par moyenne\n        z = np.maximum(W @ np.concatenate([h[v], h_nb]), 0)          # Concaténer soi-même et les voisins, puis multiplier par W\n        out.append(z / (np.linalg.norm(z) + 1e-12))                  # Normalisation L2\n    return np.array(out)\n\nh1 = sage_layer(h, neighbors, W, S=2)\nprint(h1.shape)\nprint(h1)\n```\n\n```text\n(6, 4)\n[[0.96 0.12 0.   0.24]\n [0.74 0.   0.19 0.64]\n [0.99 0.   0.   0.16]\n [0.95 0.3  0.   0.  ]\n [0.71 0.   0.   0.7 ]\n [0.81 0.   0.13 0.57]]\n```\n\nLe nœud 2 a cinq voisins, dont on ne tire que deux à chaque fois ; 4 et 5 n'en ont qu'un et sont donc tirés avec remise. L'implémentation TensorFlow officielle construit aussi pour chaque nœud une table de voisins de longueur fixe, remplie par tirages avec remise si nécessaire ; chaque lot en prélève ensuite aléatoirement $S$.\n\nLes poids $W$ sont indépendants de l'identité du nœud. Un nouveau nœud doté de caractéristiques et de voisins peut donc être traité directement par la même fonction `sage_layer`.\n\n### Trois agrégateurs\n\nLes voisins sont sans ordre : l'agrégateur devrait être invariant à leur permutation, tout en restant entraînable et expressif. Les auteurs en essaient trois :\n\n- **Mean** : moyenne élément par élément. Les auteurs construisent aussi une variante de type GCN, sans concaténation : on moyenne directement $\\{v\\}\\cup\\mathcal N(v)$, puis on multiplie par les poids. Ils l'appellent agrégateur convolutionnel.\n- **LSTM** : très expressif, mais sensible à l'ordre. Le compromis consiste à mélanger aléatoirement les voisins avant chaque passage.\n- **Pooling** : chaque voisin traverse séparément une couche entièrement connectée, puis on prend le maximum élément par élément, $\\max\\left(\\left\\{\\sigma\\left(W_{\\text{pool}}h_{u}+b\\right)\\right\\}\\right)$. Selon les auteurs, remplacer max par mean change peu le résultat.\n\n### Apprendre sans étiquettes\n\nSans étiquettes de tâche, GraphSAGE utilise une perte fondée sur le graphe :\n\n$$\nJ_{\\mathcal G}(z_u)=-\\log\\sigma\\left(z_u^\\top z_v\\right)-Q\\cdot\\mathbb{E}_{v_n\\sim P_n(v)}\\log\\sigma\\left(-z_u^\\top z_{v_n}\\right)\n$$\n\n$v$ est un nœud rencontré près de $u$ au cours d'une marche aléatoire de longueur fixe ; $v_n$ est un exemple négatif et $Q$ leur nombre. L'objectif ressemble à celui de DeepWalk, mais $z_u$ est calculé à partir des caractéristiques des voisins plutôt que lu dans une table. Avec des étiquettes, il suffit de remplacer cette perte par l'entropie croisée, ou de l'y ajouter.\n\n### Le lien avec le test WL\n\nLes auteurs remarquent aussi qu'en fixant $K$ au nombre de nœuds, les poids à l'identité et l'agrégateur à un hachage, l'algorithme 1 devient le test d'isomorphisme Weisfeiler-Lehman. GraphSAGE est une approximation continue de WL destinée à apprendre des représentations utiles des nœuds, là où WL teste l'isomorphisme.\n\n## Discussion\n\n### Trois jeux de données\n\nToutes les expériences sont inductives :\n\n- **Réseau de citations** : articles de six domaines biologiques dans Web of Science, de 2000 à 2005, soit 302,424 nœuds et un degré moyen de 9.15. L'entraînement couvre 2000 à 2004 ; le test prédit le domaine des articles de 2005.\n- **Reddit** : messages de septembre 2014 dans 50 grands sous-forums. Les 20 premiers jours servent à l'entraînement ; on prédit ensuite le sous-forum des messages suivants.\n- **PPI** : graphes d'interactions entre protéines, un par tissu humain. Vingt graphes servent à l'entraînement, deux à la validation et deux au test, pour prédire 121 étiquettes fonctionnelles des protéines. Les graphes de test restent entièrement inconnus à l'entraînement.\n\n### Résultats principaux\n\n| Méthode | Réseau de citations | Reddit | PPI |\n| --- | ---: | ---: | ---: |\n| Caractéristiques brutes | 0.575 | 0.585 | 0.422 |\n| DeepWalk + caractéristiques | 0.701 | 0.691 | — |\n| GraphSAGE-GCN | 0.772 | 0.930 | 0.500 |\n| GraphSAGE-mean | 0.820 | 0.950 | 0.598 |\n| GraphSAGE-LSTM | 0.832 | **0.954** | **0.612** |\n| GraphSAGE-pool | **0.839** | 0.948 | 0.600 |\n\nLe tableau donne le micro-F1 des variantes supervisées. L'agrégateur de type GCN termine dernier des GraphSAGE sur les trois jeux ; sur PPI, près de 0.1 le sépare des trois autres. Sa principale différence avec mean est l'absence de concaténation entre soi-même et ses voisins.\n\nLes auteurs comparent six configurations avec un test de Wilcoxon : les variantes supervisées et non supervisées sur chacun des trois jeux. LSTM, pool et mean dépassent significativement l'agrégateur GCN ; aucune différence significative ne sépare LSTM de pool. Les auteurs reconnaissent la puissance limitée d'un test à six configurations seulement.\n\nQue le LSTM, conçu pour des séquences, fonctionne aussi bien sur des ensembles non ordonnés surprend les auteurs eux-mêmes.\n\n### Le compromis entre vitesse et échantillonnage\n\n[![Figure 2 de l'article : le panneau A compare les temps d'entraînement et de test sur Reddit ; DeepWalk est bien plus lent au test que les variantes GraphSAGE. Le panneau B montre le réseau de citations : quand le nombre de voisins par couche passe de quelques unités à plus de 60, le micro-F1 monte d'environ 0.78 à 0.83, mais le temps continue d'augmenter.](/content/papers/assets/ff62a5b1aa8349edd927fc6014fd713adf4d76672507efe1a7527ff6ecdc45ca.png)](/content/papers/assets/ff62a5b1aa8349edd927fc6014fd713adf4d76672507efe1a7527ff6ecdc45ca.png)\n\n*Figure 2 de l'article (Hamilton et al.), extraite de la [**page 7 du PDF**](https://arxiv.org/pdf/1706.02216v4#page=7). Légende originale omise.*\n\nÀ gauche, les temps d'entraînement sont comparables, GraphSAGE-LSTM étant le plus lent. Au test, DeepWalk doit refaire des marches aléatoires et du SGD pour les nouveaux nœuds : il devient 100 à 500 fois plus lent que GraphSAGE.\n\nÀ droite, plus on tire de voisins, plus le F1 monte, mais avec un rendement vite décroissant et un temps toujours croissant. Les auteurs trouvent aussi $K=2$ supérieur à $K=1$ de 10% à 15% en moyenne ; passer à $K>2$ n'ajoute que 0% à 5%, pour un temps multiplié par 10 à 100.\n\n### La suite\n\nL'article renvoie pour de meilleurs scores PPI aux travaux ultérieurs de Chen et Zhu, qui règlent GraphSAGE spécialement pour PPI et ajoutent dropout, normalisation de couche et nouvel échantillonnage.\n\nL'année suivante, Rex Ying, Hamilton et Leskovec publient PinSage avec Pinterest. Entraîné sur 7.5 milliards d'exemples dans un graphe de 3 milliards de nœuds, il devient le moteur de recommandation de Pinterest. [Résumé de PinSage](https://arxiv.org/abs/1806.01973v1)\n\n## Conclusion\n\nGraphSAGE apprend une fonction qui construit les représentations. L'échantillonnage fixe le coût par lot et permet l'entraînement en mini-lots sur de grands graphes ; attribuer des poids distincts à soi-même et à ses voisins dépasse nettement la moyenne de type GCN.\n\nSur votre grand graphe, commencez par $K=2$, $S_1=25$, $S_2=10$, avec mean comme référence. PyTorch Geometric fournit `SAGEConv` et son `NeighborLoader` : inutile de réécrire l'échantillonnage ou les mini-lots.\n","imageSizes":{"/content/papers/assets/88f6d9397f20155603c7ee0daef374fb944aac5fb73ed6573a573560b5b9c6aa.png":{"width":1090,"height":384},"/content/papers/assets/ff62a5b1aa8349edd927fc6014fd713adf4d76672507efe1a7527ff6ecdc45ca.png":{"width":1092,"height":336}}}
