На этом шаге мы рассмотрим еще один пример использования метода k-средних.
Майкл Джексон выпустил десять сольных студийных альбомов. В следующем примере мы сгруппируем их, рассмотрев два измерения: длительность (в минутах) и количество дорожек. Этот пример хорошо контрастирует с предыдущим - о губернаторах, поскольку в этом исходном наборе данных кластеры легко увидеть даже без использования метода k-средних. Пример, подобный этому, может быть хорошим способом отладки реализации алгоритма кластеризации.
Этот пример представлен целиком, в виде одного листинга с кодом. Если вы посмотрите на данные об альбомах в примере ниже, прежде чем выполнить его, то станет ясно, что самые длинные альбомы Майкл Джексон записал ближе к концу карьеры. Таким образом, вероятно, следует выделить два кластера - более ранние и более поздние альбомы. Альбом "HIStory: Past, Present and Future, Book I" является выбросом и может логически оказаться в отдельном кластере с единственной единицей данных. Выбросом называется единица данных, которая выходит за пределы нормальных границ набора данных.
from __future__ import annotations from typing import List from data_point import DataPoint from pr74_1 import KMeans class Album(DataPoint): def __init__(self, name: str, year: int, length: float, tracks: float) -> None: super().__init__([length, tracks]) self.name = name self.year = year self.length = length self.tracks = tracks def __repr__(self) -> str: return f"{self.name}, {self.year}" if __name__ == "__main__": albums: List[Album] = [Album("Got to Be There", 1972, 35.45, 10), Album("Ben", 1972, 31.31, 10), Album("Music & Me", 1973, 32.09, 10), Album("Forever, Michael", 1975, 33.36, 10), Album("Off the Wall", 1979, 42.28, 10), Album("Thriller", 1982, 42.19, 9), Album("Bad", 1987, 48.16, 10), Album("Dangerous", 1991, 77.03, 14), Album("HIStory: Past, Present and Future, Book I", 1995, 148.58, 30), Album("Invincible", 2001, 77.05, 16)] kmeans: KMeans[Album] = KMeans(2, albums) clusters: List[KMeans.Cluster] = kmeans.run() for index, cluster in enumerate(clusters): print(f"Кластер {index} Средняя продолжительность {cluster.centroid.dimensions[0]} " f"Среднее количество треков {cluster.centroid.dimensions[1]}: {cluster.points}\n")
Обратите внимание: атрибуты name и year записываются только для обозначения альбома и не используются при кластеризации. Вот пример вывода результатов:
Сошлось после 1 итерации Кластер 0 Средняя продолжительность -0.5458820039179509 Среднее количество треков -0.5009878988684237: [Got to Be There, 1972, Ben, 1972, Music & Me, 1973, Forever, Michael, 1975, Off the Wall, 1979, Thriller, 1982, Bad, 1987] Кластер 1 Средняя продолжительность 1.2737246758085523 Среднее количество треков 1.1689717640263217: [Dangerous, 1991, HIStory: Past, Present and Future, Book I, 1995, Invincible, 2001]
Представляют интерес вычисленные средние значения кластеров. Обратите внимание на то, что средние значения являются z-оценками. Три альбома из кластера 1 - последние в творчестве Майкла Джексона - оказались примерно на одно стандартное отклонение длиннее, чем в среднем остальные десять его сольных альбомов.
На следующем шаге мы рассмотрим проблемы и расширения кластеризации методом k-средних.