Un guide pratique – Real Python

By | juillet 20, 2020

Formation gratuite Python

Maintenant que vous avez une compréhension de base k– signifie clustering en Python, il est temps d'effectuer k– signifie regroupement sur un jeu de données réel. Ces données contiennent des valeurs d'expression génique tirées d'un manuscrit rédigé par les chercheurs du projet d'analyse Pan-Cancer du Cancer Genome Atlas (TCGA).

Il y a 881 échantillons (lignes) représentant cinq sous-types de cancer distincts. Chaque échantillon a des valeurs d'expression génique pour 20 531 gènes (colonnes). L'ensemble de données est disponible à partir du référentiel UC Irvine Machine Learning, mais vous pouvez utiliser le code Python ci-dessous pour obtenir les données par programme.

Pour suivre les exemples ci-dessous, vous pouvez télécharger le code source en cliquant sur le lien suivant:

Dans cette section, vous allez créer un solide k– signifie un pipeline de clustering. Étant donné que vous effectuerez plusieurs transformations des données d'entrée d'origine, votre pipeline servira également de cadre de clustering pratique.

Construire un pipeline de clustering K-Means

En supposant que vous souhaitiez commencer avec un nouvel espace de noms, importez tous les modules nécessaires pour créer et évaluer le pipeline, y compris les pandas et seaborn pour des visualisations plus avancées:

>>>

Dans [1]: importer tarfile
            ...: importer urllib
            ...:
            ...: importer engourdi comme np
            ...: importer matplotlib.pyplot comme plt
            ...: importer pandas comme pd
            ...: importer Seaborn comme sns
            ...:
            ...: de sklearn.cluster importer KMeans
            ...: de sklearn.décomposition importer PCA
            ...: de sklearn.metrics importer silhouette_score, ajuste_rand_score
            ...: de sklearn.pipeline importer Pipeline
            ...: de sklearn.preprocessing importer LabelEncoder, MinMaxScaler

Téléchargez et extrayez le jeu de données TCGA de l'UCI:

>>>

Dans [2]: uci_tcga_url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00401/"
            ...: nom_archive = "TCGA-PANCAN-HiSeq-801x20531.tar.gz"

            ...: # Construisez l'url
            ...: full_download_url = urllib.analyser.urljoin(uci_tcga_url, nom_archive)
            ...:
            ...: # Téléchargez le fichier
            ...: r = urllib.demande.urlretrieve (full_download_url, nom_archive)

            ...: # Extraire les données de l'archive
            ...: le goudron = tarfile.ouvert(nom_archive, "r: gz")
            ...: le goudron.extraire tout()
            ...: le goudron.proche()

Une fois le téléchargement et l'extraction terminés, vous devriez avoir un répertoire qui ressemble à ceci:

TCGA-PANCAN-HiSeq-801x20531 /
|
├── data.csv
└── labels.csv

le KMeans La classe dans scikit-learn nécessite un tableau NumPy comme argument. Le package NumPy a un fonction d'assistance pour charger les données du fichier texte en mémoire sous forme de tableaux NumPy:

>>>

Dans [3]: fichier de données = «TCGA-PANCAN-HiSeq-801x20531 / data.csv»
            ...: labels_file = "TCGA-PANCAN-HiSeq-801x20531 / labels.csv"
            ...:
            ...: Les données = np.genfromtxt(
            ...:     fichier de données,
            ...:     délimiteur=",",
            ...:     usecols=gamme(1, 20532),
            ...:     skip_header=1
            ...: )
            ...:
            ...: true_label_names = np.genfromtxt(
            ...:     labels_file,
            ...:     délimiteur=",",
            ...:     utiliser=(1,),
            ...:     skip_header=1,
            ...:     dtype="str"
            ...: )

Consultez les trois premières colonnes de données pour les cinq premiers échantillons ainsi que les étiquettes des cinq premiers échantillons:

>>>

Dans [4]: Les données[:[:[:[:5, :3]
En dehors[4]:
tableau ([[0.        , 2.01720929, 3.26552691],
       [0.        , 0.59273209, 1.58842082],
       [0.        , 3.51175898, 4.32719872],
       [0.        , 3.66361787, 4.50764878],
       [0.        , 2.65574107, 2.82154696]])


Dans [5]: true_label_names[:[:[:[:5]
En dehors[5]: tableau (['PRAD', 'LUAD', 'PRAD', 'PRAD', 'BRCA'], dtype = '<U4')

le Les données variable contient toutes les valeurs d'expression génique de 20,531 les gènes. le true_label_names sont les types de cancer pour chacun des 881 échantillons. Le premier record de Les données correspond à la première étiquette true_labels.

Les étiquettes sont des chaînes contenant des abréviations des types de cancer:

  • BRCA: Carcinome invasif du sein
  • COAD: Adénocarcinome du côlon
  • KIRC: Carcinome rénal à cellules claires
  • LUAD: Adénocarcinome pulmonaire
  • PRAD: Adénocarcinome prostatique

Pour utiliser ces étiquettes dans les méthodes d'évaluation, vous devez d'abord convertir les abréviations en entiers avec LabelEncoder:

>>>

Dans [6]: label_encoder = LabelEncoder()

Dans [7]: true_labels = label_encoder.fit_transform(true_label_names)

Dans [8]: true_labels[:[:[:[:5]
En dehors[8]: tableau ([4, 3, 4, 4, 0])

Depuis le label_encoder a été ajusté aux données, vous pouvez voir les classes uniques représentées à l'aide .Des classes_. Stockez la longueur du tableau dans la variable n_clusters pour une utilisation ultérieure:

>>>

Dans [9]: label_encoder.Des classes_
En dehors[9]: tableau (['BRCA', 'COAD', 'KIRC', 'LUAD', 'PRAD'], dtype = '<U4')

Dans [10]: n_clusters = len(label_encoder.Des classes_)

Dans les pipelines d'apprentissage automatique pratiques, il est courant que les données subissent plusieurs séquences de transformations avant d'être intégrées à un algorithme de clustering. Vous avez appris l'importance de l'une de ces étapes de transformation, la mise à l'échelle des fonctionnalités, plus tôt dans ce didacticiel. Une technique de transformation des données tout aussi importante est réduction de la dimensionnalité, ce qui réduit le nombre d'entités dans l'ensemble de données en les supprimant ou en les combinant.

Les techniques de réduction de la dimensionnalité aident à résoudre un problème avec les algorithmes d'apprentissage automatique connus sous le nom de malédiction de la dimensionnalité. En bref, à mesure que le nombre de fonctionnalités augmente, espace caractéristique devient clairsemée. Cette rareté rend difficile pour les algorithmes de trouver des objets de données proches les uns des autres dans un espace de plus grande dimension. Puisque l'ensemble de données d'expression génique a plus 20 000 caractéristiques, il se qualifie comme un excellent candidat pour la réduction de dimensionnalité.

Analyse en composantes principales (ACP) est l'une des nombreuses techniques de réduction de dimensionnalité. PCA transforme les données d'entrée en les projetant dans un nombre inférieur de dimensions appelé Composants. Les composants capturent la variabilité des données d'entrée grâce à une combinaison linéaire des caractéristiques des données d'entrée.

Le bloc de code suivant vous présente le concept de pipelines scikit-learn. Le scikit-learn Pipeline est une implémentation concrète de l'idée abstraite d'un pipeline d'apprentissage automatique.

Vos données d'expression génique ne sont pas dans le format optimal pour le KMeans vous devrez donc créer un pipeline de prétraitement. Le pipeline mettra en œuvre une alternative au StandardScaler classe appelée MinMaxScaler pour la mise à l'échelle des fonctionnalités. Tu utilises MinMaxScaler lorsque vous ne pas Supposons que la forme de toutes vos entités suit une distribution normale.

La prochaine étape de votre pipeline de prétraitement implémentera le PCA classe pour effectuer la réduction de dimensionnalité:

>>>

Dans [11]: préprocesseur = Pipeline(
            ...:     [[[[
            ...:         ("écailleur", MinMaxScaler()),
            ...:         ("pca", PCA(n_composants=2, random_state=42)),
            ...:     ]
            ...: )

Maintenant que vous avez créé un pipeline pour traiter les données, vous allez créer un pipeline distinct pour effectuer k– signifie clustering. Vous allez remplacer les arguments par défaut suivants du KMeans classe:

  • init: Vous utiliserez "k-means ++" au lieu de "Aléatoire" pour vous assurer que les centres de gravité sont initialisés avec une certaine distance entre eux. Dans la plupart des cas, ce sera une amélioration par rapport à "Aléatoire".

  • n_init: Vous augmenterez le nombre d'initialisations pour vous assurer de trouver une solution stable.

  • max_iter: Vous augmenterez le nombre d'itérations par initialisation pour vous assurer que k-les moyens convergeront.

Construisez le k-moyen de clustering pipeline avec des arguments définis par l'utilisateur dans le KMeans constructeur:

>>>

Dans [12]: clusterer = Pipeline(
            ...:    [[[[
            ...:        (
            ...:            "kmeans",
            ...:            KMeans(
            ...:                n_clusters=n_clusters,
            ...:                init="k-means ++",
            ...:                n_init=50,
            ...:                max_iter=500,
            ...:                random_state=42,
            ...:            ),
            ...:        ),
            ...:    ]
            ...: )

le Pipeline La classe peut être chaînée pour former un pipeline plus grand. Construire un bout en bout k– signifie clustering pipeline en passant le "préprocesseur" et "clusterer" pipelines vers Pipeline:

>>>

Dans [13]: tuyau = Pipeline(
            ...:     [[[[
            ...:         ("préprocesseur", préprocesseur),
            ...:         ("clusterer", clusterer)
            ...:     ]
            ...: )

Appel .en forme() avec Les données car l'argument effectue toutes les étapes du pipeline sur le Les données:

>>>

Dans [14]: tuyau.en forme(Les données)
En dehors[14]:
Pipeline (étapes =[(«préprocesseur»[('préprocesseur'[('preprocessor'[('preprocessor'
                                                                    Pipeline (étapes =[('scaler'MinMaxScaler())[('scaler'MinMaxScaler())[('scaler'MinMaxScaler())[('scaler'MinMaxScaler())
                                                                                                                                    ('pca',
                                                                                                                                        PCA (n_components = 2, random_state = 42))])),
                                                                ('clusterer',
                                                                    Pipeline (étapes =[('kmeans'[('kmeans'[('kmeans'[('kmeans'
                                                                                                                                        KMeans (max_iter = 500, n_clusters = 5, n_init = 50,
                                                                                                                                                                    random_state = 42))]))])

Le pipeline effectue toutes les étapes nécessaires pour exécuter k-moyen de regroupement sur les données d'expression génique! En fonction de votre REPL Python, .en forme() peut imprimer un résumé du pipeline. Les objets définis à l'intérieur des pipelines sont accessibles à l'aide de leur nom d'étape.

Évaluez les performances en calculant le coefficient de silhouette:

>>>

Dans [15]: données_protraitées = tuyau[[[["préprocesseur"].transformer(Les données)

Dans [16]: preded_labels = tuyau[[[["clusterer"][[[["kmeans"].Étiquettes_

Dans [17]: silhouette_score(données_protraitées, preded_labels)
En dehors[17]: 0,5118775528450304

Calculez également l'ARI, car les étiquettes de cluster de vérité terrain sont disponibles:

>>>

Dans [18]: ajuste_rand_score(true_labels, preded_labels)
En dehors[18]: 0,722276752060253

Comme mentionné précédemment, l'échelle de chacune de ces mesures de performances de regroupement va de -1 à 1. Un coefficient de silhouette de 0 indique que les clusters se chevauchent de manière significative, et un coefficient de silhouette de 1 indique que les clusters sont bien séparés. Un score ARI de 0 indique que les étiquettes de cluster sont attribuées au hasard, et un score ARI de 1 signifie que les vraies étiquettes et les étiquettes prédites forment des clusters identiques.

Depuis que vous avez spécifié n_composants = 2 à l'étape PCA du k– signifie un pipeline de clustering, vous pouvez également visualiser les données dans le contexte des vraies étiquettes et des étiquettes prédites. Tracez les résultats en utilisant un pandas DataFrame et la bibliothèque de traçage marine:

>>>

Dans [19]: pcadf = pd.Trame de données(
            ...:     tuyau[[[["préprocesseur"].transformer(Les données),
            ...:     Colonnes=[[[["component_1", "composant_2"],
            ...: )
            ...:
            ...: pcadf[[[["preded_cluster"] = tuyau[[[["clusterer"][[[["kmeans"].Étiquettes_
            ...: pcadf[[[["true_label"] = label_encoder.inverse_transform(true_labels)

Dans [20]: plt.style.utilisation("cinquante-huit")
            ...: plt.figure(figue=(8, 8))
            ...:
            ...: scat = sns.nuage de points(
            ...:     "composant_1",
            ...:     "composant_2",
            ...:     s=50,
            ...:     Les données=pcadf,
            ...:     teinte="preded_cluster",
            ...:     style="true_label",
            ...:     palette="Set2",
            ...: )
            ...:
            ...: scat.set_title(
            ...:     "Clustering résultats de TCGA Pan-Cancer nDonnées d'expression génique "
            ...: )
            ...: plt.Légende(bbox_to_anchor=(1,05, 1), loc=2, borderaxespad=0,0)
            ...:
            ...: plt.spectacle()

Voici à quoi ressemble l'intrigue:

k signifie regrouper pca

La représentation visuelle des clusters confirme les résultats des deux métriques d'évaluation de clustering. Les performances de votre pipeline étaient plutôt bonnes. Les grappes ne se chevauchaient que légèrement et les attributions de grappes étaient bien meilleures que aléatoires.

Réglage d'un pipeline de clustering K-Means

Votre première k– signifie que le pipeline de clustering a bien fonctionné, mais qu'il y a encore place à amélioration. C'est pourquoi vous vous êtes donné la peine de créer le pipeline: vous pouvez régler les paramètres pour obtenir les résultats de clustering les plus souhaitables.

Le processus de réglage des paramètres consiste à modifier séquentiellement l'une des valeurs d'entrée des paramètres de l'algorithme et à enregistrer les résultats. À la fin du processus de réglage des paramètres, vous obtiendrez un ensemble de scores de performance, un pour chaque nouvelle valeur d'un paramètre donné. Le réglage des paramètres est une méthode puissante pour optimiser les performances de votre pipeline de clustering.

En définissant le PCA paramètre n_components = 2, vous avez réduit toutes les fonctions en deux composants ou dimensions. Cette valeur était pratique pour la visualisation sur un tracé bidimensionnel. Mais en utilisant seulement deux composants, l'étape PCA ne capturera pas tous les variance expliquée des données d'entrée.

La variance expliquée mesure l'écart entre les données transformées par l'ACP et les données d'entrée réelles. La relation entre n_components et la variance expliquée peut être visualisée dans un graphique pour vous montrer le nombre de composants dont vous avez besoin dans votre PCA pour capturer un certain pourcentage de la variance dans les données d'entrée. Vous pouvez également utiliser des mesures de performances de clustering pour évaluer le nombre de composants nécessaires pour obtenir des résultats de clustering satisfaisants.

Dans cet exemple, vous utiliserez des mesures de performances de clustering pour identifier le nombre approprié de composants dans l'étape PCA. le Pipeline la classe est puissante dans cette situation. Il vous permet d'effectuer le réglage des paramètres de base à l'aide d'un pour boucle.

Itérer sur une gamme de n_composants et enregistrer les métriques d'évaluation pour chaque itération:

>>>

Dans [21]: # Listes vides pour contenir les mesures d'évaluation
            ...: silhouette_scores = []
            ...: ari_scores = []
            ...: pour n dans gamme(2, 11):
            ...:     # Ceci définit le nombre de composants pour pca,
            ...:     # mais laisse les autres étapes inchangées
            ...:     tuyau[[[["préprocesseur"][[[["pca"].n_composants = n
            ...:     tuyau.en forme(Les données)
            ...:
            ...:     silhouette_coef = silhouette_score(
            ...:         tuyau[[[["préprocesseur"].transformer(Les données),
            ...:         tuyau[[[["clusterer"][[[["kmeans"].Étiquettes_,
            ...:     )
            ...:     ari = ajusté_rand_score(
            ...:         true_labels,
            ...:         tuyau[[[["clusterer"][[[["kmeans"].Étiquettes_,
            ...:     )
            ...:
            ...:     # Ajouter des métriques à leurs listes
            ...:     silhouette_scores.ajouter(silhouette_coef)
            ...:     ari_scores.ajouter(Ari)

Tracez les métriques d'évaluation en fonction de n_composants pour visualiser la relation entre l'ajout de composants et les performances du k-signifie les résultats de clustering:

>>>

Dans [22]: plt.style.utilisation("cinq trente-huit")
            ...: plt.figure(figue=(6, 6))
            ...: plt.terrain(
            ...:     gamme(2, 11),
            ...:     silhouette_scores,
            ...:     c="# 008fd5",
            ...:     étiquette="Coefficient de silhouette",
            ...: )
            ...: plt.terrain(gamme(2, 11), ari_scores, c="# fc4f30", étiquette="ARI")
            ...:
            ...: plt.xlabel("n_composants")
            ...: plt.Légende()
            ...: plt.Titre("Performances de clustering en fonction de n_components")
            ...: plt.tight_layout()
            ...: plt.spectacle()

Le code ci-dessus génère un graphique montrant les mesures de performance en fonction de n_composants:

k signifie évaluation des performances

Il y a deux points à retenir de cette figure:

  1. le coefficient de silhouette diminue linéairement. Le coefficient de silhouette dépend de la distance entre les points, donc à mesure que le nombre de dimensions augmente, la parcimonie augmente.

  2. le ARI s'améliore considérablement lorsque vous ajoutez des composants. Il semble commencer à diminuer après n_composants = 7, ce serait donc la valeur à utiliser pour présenter les meilleurs résultats de clustering de ce pipeline.

Comme la plupart des décisions d'apprentissage automatique, vous devez équilibrer l'optimisation des métriques d'évaluation de clustering avec l'objectif de la tâche de clustering. Dans les situations où les étiquettes de cluster sont disponibles, comme c'est le cas avec l'ensemble de données sur le cancer utilisé dans ce didacticiel, l'IRA est un choix raisonnable. ARI quantifie la précision avec laquelle votre pipeline a pu réaffecter les étiquettes de cluster.

Le coefficient de silhouette, en revanche, est un bon choix pour les regroupements exploratoires car il aide à identifier les sous-groupes. Ces sous-grappes méritent une enquête supplémentaire, ce qui peut conduire à des informations nouvelles et importantes.