neuronale Netzwerke und Clustering Algorithmen scheinen Welten voneinander auseinander zu sein. Neuronale Netze werden in der Regel im überwachten Lernen verwendet, wobei das Ziel darin besteht, neue Daten basierend auf Mustern zu kennzeichnen, die aus einem beschrifteten Datensatz gelernt werden. Das Clustering ist dagegen normalerweise eine unbeaufsichtigte Aufgabe: Wir versuchen, Beziehungen in Daten ohne Zugriff auf Bodenwahrheitsbezeichnungen aufzudecken.
Wie sich herausstellt, Tiefes Lernen kann unglaublich nützlich für Clustering -Probleme sein. Hier ist die Schlüsselidee: Angenommen, wir schulen ein neuronales Netzwerk mit einer Verlustfunktion, die etwas widerspiegelt, das uns am Herzen liegt – sagen wir, wie intestine wir Beispiele klassifizieren oder getrennt werden können. Wenn das Netzwerk einen geringen Verlust erreicht, können wir schließen, dass die Darstellungen Es erfasst (insbesondere in der zweiten Final) eine sinnvolle Struktur in den Daten. Mit anderen Worten, diese Zwischendarstellungen codieren das, was das Netzwerk über die Aufgabe gelernt hat.
Was passiert additionally, wenn wir einen Clustering -Algorithmus (wie Kmeans) für diese Darstellungen ausführen? Im Idealfall haben wir Cluster, die die gleiche zugrunde liegende Struktur widerspiegeln, die das Netzwerk für die Erfassung geschult wurde.
Ahh, das ist viel! Hier ist ein Bild:

Wie auf dem Bild zu sehen ist, erhalten wir, wenn wir unsere Eingaben bis zur zweitletzten Ebene durchführen, einen Vektor mit Kₘ-Werten heraus, was vermutlich viel niedriger ist als die Menge an Eingängen, mit denen wir begonnen haben, wenn wir alles richtig gemacht haben. Weil die Ausgangsschicht Betrachtet diesen Vektor ausschließlich bei VorhersagenWenn unsere Vorhersagen intestine sind, können wir zu dem Schluss kommen, dass dieser Vektor einige wichtige Informationen über unsere Daten zusammenfasst. Das Clustering in diesem Bereich ist aussagekräftiger als das Clustering von Rohdaten, da wir für die tatsächlich wichtigen Funktionen gefiltert haben.
Dies ist die grundlegende Idee dahinter DeepType– A Neurales Netzwerk Ansatz zum Clustering. Anstatt Rohdaten direkt zu klugen, lernt DeepType zunächst eine aufgabenrelevante Darstellung durch überwachtes Coaching und führt dann in diesem gelernten Raum ein Clustering durch.
Dies wirft jedoch eine Frage auf-wenn wir bereits Bodenwahrheitsbezeichnungen haben, warum müssten wir dann Clustering ausführen? Wenn wir uns nur mit unseren Etiketten zusammenschließen, würde das nicht ein perfektes Clustering schaffen? Für neue Datenpunkte konnten wir dann einfach unser neuronales Netz ausführen, das Etikett vorhersagen und den Punkt angemessen zusammenfassen.
Wie sich herausstellt, in einigen Kontexten,, Wir kümmern uns mehr um die Beziehungen zwischen unseren Datenpunkten als den Beschriftungen selbst. Im Papier, das DeepType einführteZum Beispiel verwendeten die Autoren die Idee, um verschiedene Gruppierungen von Patienten mit Brustkrebs zu finden, die auf genetischen Daten basieren, was in einem biologischen Kontext sehr nützlich ist. Sie fanden dann fest, dass diese Gruppen sehr stark mit den Überlebensraten korrelierten, was sinnvoll ist, da die Darstellungen, auf die sie sich zusammengetanten, mit biologischem Wissen verankert waren.
Verfeinerung der Idee: DeepTypes Verlustfunktion
Zu diesem Zeitpunkt verstehen wir die Kernidee: trainieren Sie ein neuronales Netzwerk, um eine aufgabenrelevante Darstellung zu erlernen und dann in diesem Raum zu kluster. Wir können jedoch einige geringfügige Änderungen vornehmen, um diesen Prozess besser zu machen.
Für den Anfang möchten wir, dass die Cluster, die wir produzieren, nach Möglichkeit kompakt sind. Mit anderen Worten, wir hätten viel lieber die Scenario auf dem Bild hyperlinks als rechts:

Dazu möchten wir die Darstellungen von Datenpunkten in denselben Clustern so nahe wie möglich zusammenhalten. Zu diesem Zweck fügen wir unserer Verlustfunktion eine Begriff hinzu, die den Abstand zwischen der Darstellung unserer Eingabe und dem Zentrum des Clusters bestraft, dem sie zugewiesen wurden. So wird unsere Verlustfunktion

Wo D ist eine Entfernungsfunktion zwischen Vektoren, dh das Quadrat der Norm der Differenz zwischen den Vektoren (wie im Originalpapier verwendet).
Aber warte, wie bekommen wir die Cluster -Zentren, wenn wir das Netzwerk noch nicht trainiert haben? Um das umzugehen, führt DeepType das folgende Verfahren durch:
- Trainieren Sie ein Modell nur für den primären Verlust
- Erstellen Sie Cluster im Repräsentationsraum (unter Verwendung von EG Kmeans oder Ihrem Lieblingsalgorithmus)
- Trainieren Sie das Modell mit dem modifizierten Verlust
- Gehen Sie zurück zu Schritt 2 und wiederholen Sie, bis wir konvergieren
Schließlich erzeugt dieses Verfahren kompakte Cluster, die hoffentlich unserem Interesseverlust entsprechen.
Wichtige Eingaben finden
In Kontexten, in denen DeepType nützlich ist, kümmern wir uns neben der Pflege von Clustern auch darum, welche Eingaben die informativsten/wichtigsten sind. Das Papier, das beispielsweise DeepType einführte, battle daran interessiert zu bestimmen, welche Gene die wichtigste für die Bestimmung eines Krebs -Subtyps eines Menschen waren – diese Informationen sind für einen Biologen sicherlich nützlich. Viele andere Kontexte würden auch solche Informationen interessant finden – in der Tat ist es schwierig, sich eine auszudenken, die es nicht tun würde.
In einem tiefen Lernkontext können wir einen Eingang als wichtig ansehen, wenn die Größe der ihm von den Knoten in der ersten Schicht zugewiesenen Gewichten hoch ist. Wenn die meisten unserer Knoten für die Eingabe ein Gewicht nahe 0 haben, trägt es im Gegensatz dazu nicht viel zu unserer endgültigen Vorhersage und ist daher wahrscheinlich nicht so wichtig.
Wir führen somit einen endgültigen Verlustdauer ein – a Sparsity -Verlust –Dies wird unser neuronales Netz ermutigen, so viele Eingangsgewichte wie möglich auf 0 zu bringen. Damit wird unser endgültiger modifizierter DeepType -Verlust

Wo der Beta-Time period der Distanzbegriff battle, den wir zuvor hatten, und der Alpha-Begriff bestraft effektiv eine hohe „Größe“ der ersten Layer-Gewichtsmatrix².
Wir ändern auch die vierstufige Prozedur aus dem vorherigen Abschnitt geringfügig. Anstatt nur im ersten Schritt auf der MSE zu trainieren, trainieren wir sowohl im MSE als auch mit dem Sparsity -Verlust im Vorabstieg. Laut den Autoren sieht unsere endgültige DeepType -Struktur so aus:

Spielen mit DeepType
Im Rahmen meiner Recherche habe ich eine veröffentlicht Open-Supply-Implementierung von DeepType hier. Sie können es zusätzlich von PIP herunterladen, indem Sie dies tun pip set up torch-deeptype .
Das DeepType -Paket verwendet eine ziemlich einfache Infrastruktur, um alles zu testen. Als Beispiel erstellen wir einen synthetischen Datensatz mit vier Clustern und 20 Eingängen, von denen nur 5 zum Ausgang beitragen:
import numpy as np
import torch
from torch.utils.knowledge import TensorDataset, DataLoader
# 1) Configuration
n_samples = 1000
n_features = 20
n_informative = 5 # variety of "necessary" options
n_clusters = 4 # variety of ground-truth clusters
noise_features = n_features - n_informative
# 2) Create distinct cluster facilities within the informative subspace
# (unfold out so clusters are nicely separated)
informative_centers = np.random.randn(n_clusters, n_informative) * 5
# 3) Assign every pattern to a cluster, then pattern round that middle
X_informative = np.zeros((n_samples, n_informative))
y_clusters = np.random.randint(0, n_clusters, dimension=n_samples)
for i, c in enumerate(y_clusters):
middle = informative_centers(c)
X_informative(i) = middle + np.random.randn(n_informative)
# 4) Generate pure noise for the remaining options
X_noise = np.random.randn(n_samples, noise_features)
# 5) Concatenate informative + noise options
X = np.hstack((X_informative, X_noise)) # form (1000, 20)
y = y_clusters # form (1000,)
# 6) Convert to torch tensors and construct DataLoader
X_tensor = torch.from_numpy(X).float()
y_tensor = torch.from_numpy(y).lengthy()
dataset = TensorDataset(X_tensor, y_tensor)
train_loader = DataLoader(dataset, batch_size=64, shuffle=True)
So sieht unsere Daten aus, wenn wir eine PCA zeichnen:

Wir werden dann a definierenDeeptypeModel– Es kann jede Infrastruktur sein, solange sie das implementiert ahead Anwesend get_input_layer_weights Und get_hidden_representations Funktionen:
import torch
import torch.nn as nn
from torch_deeptype import DeeptypeModel
class MyNet(DeeptypeModel):
def __init__(self, input_dim: int, hidden_dim: int, output_dim: int):
tremendous().__init__()
self.input_layer = nn.Linear(input_dim, hidden_dim)
self.h1 = nn.Linear(hidden_dim, hidden_dim)
self.cluster_layer = nn.Linear(hidden_dim, hidden_dim // 2)
self.output_layer = nn.Linear(hidden_dim // 2, output_dim)
def ahead(self, x: torch.Tensor) -> torch.Tensor:
# Discover how ahead() will get the hidden representations
hidden = self.get_hidden_representations(x)
return self.output_layer(hidden)
def get_input_layer_weights(self) -> torch.Tensor:
return self.input_layer.weight
def get_hidden_representations(self, x: torch.Tensor) -> torch.Tensor:
x = torch.relu(self.input_layer(x))
x = torch.relu(self.h1(x))
x = torch.relu(self.cluster_layer(x))
return x
Dann erstellen wir eine DeeptypeTrainer und Zug:
from torch_deeptype import DeeptypeTrainer
coach = DeeptypeTrainer(
mannequin = MyNet(input_dim=20, hidden_dim=64, output_dim=5),
train_loader = train_loader,
primary_loss_fn = nn.CrossEntropyLoss(),
num_clusters = 4, # Ok in KMeans
sparsity_weight = 0.01, # α for L₂ sparsity on enter weights
cluster_weight = 0.5, # β for cluster‐rep loss
verbose = True # print per-epoch loss summaries
)
coach.prepare(
main_epochs = 15, # epochs for joint part
main_lr = 1e-4, # LR for joint part
pretrain_epochs = 10, # epochs for pretrain part
pretrain_lr = 1e-3, # LR for pretrain (defaults to main_lr if None)
train_steps_per_batch = 8, # interior updates per batch in joint part
)
Nach dem Coaching können wir die wichtigen Eingaben dann leicht extrahieren
sorted_idx = coach.mannequin.get_sorted_input_indices()
print("High 5 options by significance:", sorted_idx(:5).tolist())
print(coach.mannequin.get_input_importance())
>> High 5 options by significance: (3, 1, 4, 2, 0)
>> tensor((0.7594, 0.8327, 0.8003, 0.9258, 0.8141, 0.0107, 0.0199, 0.0329, 0.0043,
0.0025, 0.0448, 0.0054, 0.0119, 0.0021, 0.0190, 0.0055, 0.0063, 0.0073,
0.0059, 0.0189), grad_fn=<LinalgVectorNormBackward0>)
Was großartig ist, wir haben die 5 wichtigen Eingaben wie erwartet zurückbekommen!
Wir können die Cluster auch mit der Darstellungsschicht problemlos extrahieren und sie zeichnen:
centroids, labels = coach.get_clusters(dataset)
plt.determine(figsize=(8, 6))
plt.scatter(
parts(:, 0),
parts(:, 1),
c=labels,
cmap='tab10',
s=20,
alpha=0.7
)
plt.xlabel('Principal Part 1')
plt.ylabel('Principal Part 2')
plt.title('PCA of Artificial Dataset')
plt.colorbar(label='True Cluster')
plt.tight_layout()
plt.present()

Und Increase, das ist alles!
Abschluss
Obwohl DeepType nicht das richtige Werkzeug für jedes Drawback ist, bietet es eine leistungsstarke Möglichkeit, Domänenwissen in den Clustering -Prozess zu integrieren. Wenn Sie sich additionally mit einer aussagekräftigen Verlustfunktion und dem Wunsch befinden, Struktur in Ihren Daten aufzudecken – geben Sie DeepType einen Schuss!
Bitte kontaktieren Sie (E -Mail geschützt) Für Anfragen. Alle Bilder vom Autor, sofern nicht anders angegeben.
- Biologen haben eine Reihe von Krebs -Subtypen für den Brustkrebs der breiteren Kategorie ermittelt. Obwohl ich kein Experte bin, kann man davon ausgehen, dass diese Subtypen aus einem Grund von Biologen identifiziert wurden. Die Autoren trainierten ihr Modell, um den Subtyp für einen Patienten vorherzusagen, was den biologischen Kontext lieferte, der zur Herstellung neuer, interessanter Cluster erforderlich battle. Angesichts des Ziels bin ich mir jedoch nicht sicher, warum die Autoren sich entschieden haben, Subtypen anstelle von Patientenergebnissen direkt vorherzusagen – tatsächlich wette ich, dass die Ergebnisse eines solchen Experiments interessant wären.
- Die vorgestellte Norm ist definiert als

Wir transponieren W, da wir die Spalten der Gewichtsmatrix und nicht die Zeilen bestrafen wollen. Dies ist wichtig, weil in einer vollständig verbundenen neuronalen Netzwerkschicht, Jede Spalte der Gewichtsmatrix entspricht einer Eingangsfunktion. Indem wir die Norm ℓ2,1 auf die transponierte Matrix anwenden, empfehlen wir, dass ganze Eingabefunktionen auf Null gesetzt werden, was die Sparsität auf Merkmalsebene fördert
Titelbildquelle: Hier
