Da wir einen unüberwachten Lernalgorithmus verwenden, gibt es kein allgemein verfügbares Maß für die Genauigkeit. Wir können jedoch Domänenwissen verwenden, um unsere Gruppen zu validieren.

Bei einer optischen Überprüfung der Gruppen können wir erkennen, dass einige Benchmarking-Gruppen über eine Mischung aus Economic system- und Luxushotels verfügen, was geschäftlich keinen Sinn ergibt, da die Nachfrage nach Resorts grundsätzlich unterschiedlich ist.

Wir können zu den Daten scrollen und einige dieser Unterschiede feststellen, aber können wir unser eigenes Maß für die Genauigkeit finden?

Wir möchten eine Funktion erstellen, um die Konsistenz der empfohlenen Benchmarking-Units für jedes Function zu messen. Eine Möglichkeit hierfür besteht darin, die Varianz in jedem Function für jedes Set zu berechnen. Für jeden Cluster können wir einen Durchschnitt der Varianz jedes Options berechnen und dann den Durchschnitt der Varianz jedes Hotelclusters bilden, um einen Gesamtwert für das Modell zu erhalten.

Aus unserem Fachwissen wissen wir, dass wir, um einen vergleichbaren Benchmark-Satz einzurichten, Resorts der gleichen Marke, möglichst des gleichen Marktes und des gleichen Landes priorisieren müssen. Und wenn wir unterschiedliche Märkte oder Länder verwenden, sollte die Marktstufe dieselbe sein.

Vor diesem Hintergrund möchten wir, dass unsere Messung eine höhere Strafe für die Varianz dieser Merkmale vorsieht. Zu diesem Zweck verwenden wir einen gewichteten Durchschnitt, um die Varianz jedes Benchmark-Units zu berechnen. Wir drucken die Varianz der Hauptmerkmale und der sekundären Merkmale außerdem separat aus.

Zusammenfassend müssen wir zur Erstellung unseres Genauigkeitsmaßes Folgendes tun:

  1. Varianz für kategoriale Variablen berechnen: Ein gängiger Ansatz besteht darin, ein „entropiebasiertes“ Maß zu verwenden, bei dem eine größere Vielfalt in Kategorien eine höhere Entropie (Varianz) anzeigt.
  2. Varianz für numerische Variablen berechnen: Wir können die Standardabweichung oder den Bereich (Differenz zwischen Maximal- und Minimalwerten) berechnen. Dies misst die Streuung der numerischen Daten innerhalb jedes Clusters.
  3. Normalisieren Sie die Daten: Normalisieren Sie die Varianzwerte für jede Kategorie, bevor Sie Gewichte anwenden, um sicherzustellen, dass kein einzelnes Merkmal den gewichteten Durchschnitt allein aufgrund von Skalenunterschieden dominiert.
  4. Gewichtungen für unterschiedliche Metriken anwenden: Gewichten Sie jeden Varianztyp basierend auf seiner Bedeutung für die Clusterlogik.
  5. Berechnen gewichteter Durchschnittswerte: Berechnen Sie den gewichteten Durchschnitt dieser Varianzwerte für jeden Cluster.
  6. Aggregieren von Punktzahlen über Cluster hinweg: Der Gesamtwert ist der Durchschnitt dieser gewichteten Varianzwerte über alle Cluster oder Zeilen hinweg. Ein niedrigerer Durchschnittswert würde darauf hinweisen, dass unser Modell ähnliche Resorts effektiv zusammenfasst und so die Varianz innerhalb der Cluster minimiert.
from scipy.stats import entropy
from sklearn.preprocessing import MinMaxScaler
from collections import Counter

def categorical_variance(information):
"""
Calculate entropy for a categorical variable from a listing.
The next entropy worth signifies datas with various courses.
A decrease entropy worth signifies a extra homogeneous subset of information.
"""
# Depend frequency of every distinctive worth
value_counts = Counter(information)
total_count = sum(value_counts.values())
chances = (rely / total_count for rely in value_counts.values())
return entropy(chances)

#set scoring weights giving greater weights to a very powerful options
scoring_weights = {"BRAND": 0.3,
"Room_count": 0.025,
"Market": 0.25,
"Nation": 0.15,
"Market Tier": 0.15,
"HCLASS": 0.05,
"Demand": 0.025,
"Value vary": 0.025,
"distance_to_airport": 0.025}

def calculate_weighted_variance(df, weights):
"""
Calculate the weighted variance rating for clusters within the dataset
"""
# Initialize a DataFrame to retailer the variances
variance_df = pd.DataFrame()

# 1. Calculate variances for numerical options
numerical_features = ('Room_count', 'Demand', 'Value vary', 'distance_to_airport')
for function in numerical_features:
variance_df(f'{function}') = df(function).apply(np.var)

# 2. Calculate entropy for categorical options
categorical_features = ('BRAND', 'Market','Nation','Market Tier','HCLASS')
for function in categorical_features:
variance_df(f'{function}') = df(function).apply(categorical_variance)

# 3. Normalize the variance and entropy values
scaler = MinMaxScaler()
normalized_variances = pd.DataFrame(scaler.fit_transform(variance_df),
columns=variance_df.columns,
index=variance_df.index)

# 4. Compute weighted common

cat_weights = {f'{function}': weights(f'{function}') for function in categorical_features}
num_weights = {f'{function}': weights(f'{function}') for function in numerical_features}

cat_weighted_scores = normalized_variances(categorical_features).mul(cat_weights)
df('cat_weighted_variance_score') = cat_weighted_scores.sum(axis=1)

num_weighted_scores = normalized_variances(numerical_features).mul(num_weights)
df('num_weighted_variance_score') = num_weighted_scores.sum(axis=1)

return df('cat_weighted_variance_score').imply(), df('num_weighted_variance_score').imply()

Um unseren Code sauber zu halten und unsere Experimente zu verfolgen, definieren wir auch eine Funktion zum Speichern der Ergebnisse unserer Experimente.

# outline a perform to retailer the outcomes of our experiments
def model_score(information: pd.DataFrame,
weights: dict = scoring_weights,
model_name: str ="model_0"):
cat_score,num_score = calculate_weighted_variance(information,weights)
outcomes ={"Mannequin": model_name,
"Major options rating": cat_score,
"Secondary options rating": num_score}
return outcomes

model_0_score= model_score(results_model_0,scoring_weights)
model_0_score

Ergebnisse des Basismodells.

Da wir nun eine Foundation haben, wollen wir sehen, ob wir unser Modell verbessern können.

Verbesserung unseres Modells durch Experimente

Bisher mussten wir nicht wissen, was unter der Haube vor sich ging, wenn wir diesen Code ausführten:

nns = NearestNeighbors()
nns.match(data_scaled)
nns_results_model_0 = nns.kneighbors(data_scaled)(1)

Um unser Modell zu verbessern, müssen wir die Modellparameter verstehen und wissen, wie wir mit ihnen interagieren können, um bessere Benchmark-Units zu erhalten.

Sehen wir uns zunächst die Scikit Be taught-Dokumentation und den Quellcode an:

# the under is taken instantly from scikit be taught supply

from sklearn.neighbors._base import KNeighborsMixin, NeighborsBase, RadiusNeighborsMixin

class NearestNeighbors_(KNeighborsMixin, RadiusNeighborsMixin, NeighborsBase):
"""Unsupervised learner for implementing neighbor searches.
Parameters
----------
n_neighbors : int, default=5
Variety of neighbors to make use of by default for :meth:`kneighbors` queries.

radius : float, default=1.0
Vary of parameter area to make use of by default for :meth:`radius_neighbors`
queries.

algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, default='auto'
Algorithm used to compute the closest neighbors:

- 'ball_tree' will use :class:`BallTree`
- 'kd_tree' will use :class:`KDTree`
- 'brute' will use a brute-force search.
- 'auto' will try to resolve essentially the most applicable algorithm
based mostly on the values handed to :meth:`match` methodology.

Observe: becoming on sparse enter will override the setting of
this parameter, utilizing brute power.

leaf_size : int, default=30
Leaf dimension handed to BallTree or KDTree. This will have an effect on the
velocity of the development and question, in addition to the reminiscence
required to retailer the tree. The optimum worth relies on the
nature of the issue.

metric : str or callable, default='minkowski'
Metric to make use of for distance computation. Default is "minkowski", which
ends in the usual Euclidean distance when p = 2. See the
documentation of `scipy.spatial.distance
<https://docs.scipy.org/doc/scipy/reference/spatial.distance.html>`_ and
the metrics listed in
:class:`~sklearn.metrics.pairwise.distance_metrics` for legitimate metric
values.

p : float (constructive), default=2
Parameter for the Minkowski metric from
sklearn.metrics.pairwise.pairwise_distances. When p = 1, that is
equal to utilizing manhattan_distance (l1), and euclidean_distance
(l2) for p = 2. For arbitrary p, minkowski_distance (l_p) is used.

metric_params : dict, default=None
Further key phrase arguments for the metric perform.
"""

def __init__(
self,
*,
n_neighbors=5,
radius=1.0,
algorithm="auto",
leaf_size=30,
metric="minkowski",
p=2,
metric_params=None,
n_jobs=None,
):
tremendous().__init__(
n_neighbors=n_neighbors,
radius=radius,
algorithm=algorithm,
leaf_size=leaf_size,
metric=metric,
p=p,
metric_params=metric_params,
n_jobs=n_jobs,
)

Hier ist ziemlich viel los.

Der Nearestneighbor Klasse erbt vonNeighborsBasedie Fallklasse für Nearest-Neighbor-Schätzer. Diese Klasse behandelt die allgemeinen Funktionen, die für Nearest-Neighbor-Suchen erforderlich sind, wie z. B.

  • n_neighbors (die Anzahl der zu verwendenden Nachbarn)
  • Radius (der Radius für radiusbasierte Nachbarsuchen)
  • Algorithmus (der Algorithmus, der zur Berechnung der nächsten Nachbarn verwendet wird, z. B. „ball_tree“, „kd_tree“ oder „brute“)
  • Metrik (die zu verwendende Distanzmetrik)
  • metric_params (zusätzliche Schlüsselwortargumente für die Metrikfunktion)

Der Nearestneighbor Klasse erbt auch vonKNeighborsMixin Und RadiusNeighborsMixinKlassen. Diese Mixin-Klassen fügen spezielle Neighbor-Search-Funktionalitäten zum Nearestneighbor

  • KNeighborsMixin bietet die Funktion, die nächste feste Anzahl okay von Nachbarn zu einem Punkt zu finden. Dies geschieht, indem die Distanz zu den Nachbarn und ihren Indizes ermittelt und ein Diagramm der Verbindungen zwischen Punkten basierend auf den k-nächsten Nachbarn jedes Punkts erstellt wird.
  • RadiusNeighborsMixin basiert auf dem Radius-Nachbarn-Algorithmus, der alle Nachbarn innerhalb eines bestimmten Radius eines Punkts findet. Diese Methode ist in Szenarien nützlich, in denen der Fokus auf der Erfassung aller Punkte innerhalb einer sinnvollen Entfernungsschwelle und nicht einer festen Anzahl von Punkten liegt.

Basierend auf unserem Szenario bietet KNeighborsMixin die Funktionalität, die wir benötigen.

Bevor wir unser Modell verbessern können, müssen wir einen Schlüsselparameter verstehen: die Distanzmetrik.

In der Dokumentation wird erwähnt, dass der NearestNeighbor-Algorithmus standardmäßig die „Minkowski“-Distanz verwendet, und es wird auf die SciPy-API verwiesen.

In scipy.spatial.distancekönnen wir zwei mathematische Darstellungen der „Minkowski“-Distanz sehen:

∥u−v∥ p​=( i ∑​∣ui​−vi​∣ p ) 1/p

Diese Formel berechnet die p-te Wurzel der Summe der Potenzdifferenzen aller Elemente.

Die zweite mathematische Darstellung der „Minkowski“-Distanz lautet:

∥u−v∥ p​=( i ∑​wi​(∣ui​−vi​∣ p )) 1/p

Dies ist dem ersten sehr ähnlich, führt aber Gewichte ein wi auf die Unterschiede, indem bestimmte Dimensionen hervorgehoben oder weniger hervorgehoben werden. Dies ist nützlich, wenn bestimmte Merkmale relevanter sind als andere. Standardmäßig ist die Einstellung Keine, wodurch allen Merkmalen die gleiche Gewichtung von 1,0 zugewiesen wird.

Dies ist eine großartige Choice zur Verbesserung unseres Modells, da wir dadurch Domänenwissen an unser Modell weitergeben und die für die Benutzer relevantesten Ähnlichkeiten hervorheben können.

Wenn wir uns die Formeln ansehen, sehen wir den Parameter. pDieser Parameter beeinflusst den „Pfad“, den der Algorithmus zur Berechnung der Entfernung nimmt. Standardmäßig ist p=2, was die euklidische Distanz darstellt.

Sie können sich die euklidische Distanz so vorstellen, als würde man die Distanz berechnen, indem man eine gerade Linie zwischen zwei Punkten zieht. Normalerweise ist das die kürzeste Distanz, aber das ist nicht immer die beste Artwork, die Distanz zu berechnen, insbesondere in Räumen mit höheren Dimensionen. Weitere Informationen dazu, warum das so ist, finden Sie in diesem großartigen Artikel on-line: https://bib.dbvis.de/uploadedFiles/155.pdf

Ein anderer gängiger Wert für p ist 1. Dies stellt die Manhattan-Distanz dar. Stellen Sie es sich als die Entfernung zwischen zwei Punkten vor, gemessen entlang eines gitterartigen Pfades.

Wenn wir andererseits p gegen unendlich erhöhen, erhalten wir die Tschebyscheff-Distanz, definiert als die maximale absolute Differenz zwischen entsprechenden Elementen der Vektoren. Es misst im Wesentlichen die Differenz im schlimmsten Fall und ist daher in Szenarien nützlich, in denen Sie sicherstellen möchten, dass kein einzelnes Merkmal zu stark variiert.

Durch das Lesen und Vertrautmachen mit der Dokumentation haben wir einige mögliche Optionen zur Verbesserung unseres Modells entdeckt.

Standardmäßig ist n_neighbors 5, aber für unseren Benchmark-Satz möchten wir jedes Resort mit den 3 ähnlichsten Resorts vergleichen. Dazu müssen wir n_neighbors = 4 (Betreffhotel + 3 Friends) festlegen.

nns_1= NearestNeighbors(n_neighbors=4)
nns_1.match(data_scaled)
nns_1_results_model_1 = nns_1.kneighbors(data_scaled)(1)
results_model_1 = clean_results(nns_results=nns_1_results_model_1,
encoders=encoders,
information=data_clean)
model_1_score= model_score(results_model_1,scoring_weights,model_name="baseline_k_4")
model_1_score
Leichte Verbesserung unserer Hauptfunktionen. Bild vom Autor

Basierend auf der Dokumentation können wir Gewichte an die Distanzberechnung übergeben, um die Beziehung zwischen einigen Merkmalen hervorzuheben. Basierend auf unserem Fachwissen haben wir die Merkmale identifiziert, die wir hervorheben möchten, in diesem Fall Marke, Markt, Land und Marktstufe.

# arrange weights for distance calculation
weights_dict = {"BRAND": 5,
"Room_count": 2,
"Market": 4,
"Nation": 3,
"Market Tier": 3,
"HCLASS": 1.5,
"Demand": 1,
"Value vary": 1,
"distance_to_airport": 1}
# Remodel the wieghts dictionnary into a listing by holding the scaled information column order
weights = ( weights_dict(idx) for idx in listing(scaler.get_feature_names_out()))

nns_2= NearestNeighbors(n_neighbors=4,metric_params={ 'w': weights})
nns_2.match(data_scaled)
nns_2_results_model_2 = nns_2.kneighbors(data_scaled)(1)
results_model_2 = clean_results(nns_results=nns_2_results_model_2,
encoders=encoders,
information=data_clean)
model_2_score= model_score(results_model_2,scoring_weights,model_name="baseline_with_weights")
model_2_score

Die Bewertung der primären Merkmale verbessert sich ständig. Bild vom Autor

Die Weitergabe von Domänenwissen an das Modell über Gewichte erhöhte die Punktzahl erheblich. Als Nächstes testen wir die Auswirkungen des Distanzmaßes.

Bisher haben wir die euklidische Distanz verwendet. Sehen wir uns an, was passiert, wenn wir stattdessen die Manhattan-Distanz verwenden.

nns_3= NearestNeighbors(n_neighbors=4,p=1,metric_params={ 'w': weights})
nns_3.match(data_scaled)
nns_3_results_model_3 = nns_3.kneighbors(data_scaled)(1)
results_model_3 = clean_results(nns_results=nns_3_results_model_3,
encoders=encoders,
information=data_clean)
model_3_score= model_score(results_model_3,scoring_weights,model_name="Manhattan_with_weights")
model_3_score
Deutlicher Rückgang des Primärscores. Bild vom Autor

Die Reduzierung von p auf 1 brachte einige gute Verbesserungen. Mal sehen, was passiert, wenn p sich der Unendlichkeit nähert.

Um die Tschebyscheff-Distanz zu verwenden, ändern wir den metrischen Parameter in Chebyshev. Die standardmäßige Tschebyscheff-Metrik von sklearn hat keinen Gewichtsparameter. Um dies zu umgehen, definieren wir eine benutzerdefinierte weighted_chebyshev metrisch.

#  Outline the customized weighted Chebyshev distance perform
def weighted_chebyshev(u, v, w):
"""Calculate the weighted Chebyshev distance between two factors."""
return np.max(w * np.abs(u - v))

nns_4 = NearestNeighbors(n_neighbors=4,metric=weighted_chebyshev,metric_params={ 'w': weights})
nns_4.match(data_scaled)
nns_4_results_model_4 = nns_4.kneighbors(data_scaled)(1)
results_model_4 = clean_results(nns_results=nns_4_results_model_4,
encoders=encoders,
information=data_clean)
model_4_score= model_score(results_model_4,scoring_weights,model_name="Chebyshev_with_weights")
model_4_score

Besser als der Ausgangswert, aber höher als im vorherigen Experiment. Bild vom Autor

Durch Experimente ist es uns gelungen, die Varianzwerte der primären Merkmale zu senken.

Lassen Sie uns die Ergebnisse visualisieren.

results_df = pd.DataFrame((model_0_score,model_1_score,model_2_score,model_3_score,model_4_score)).set_index("Mannequin")
results_df.plot(variety='barh')
Ergebnisse des Experiments. Bild vom Autor

Die Verwendung der Manhattan-Distanz mit Gewichten scheint unseren Anforderungen entsprechend die genauesten Benchmark-Sätze zu liefern.

Der letzte Schritt vor der Implementierung der Benchmark-Units besteht darin, die Units mit den höchsten Punktzahlen für die primären Funktionen zu untersuchen und festzustellen, welche Schritte mit ihnen unternommen werden sollten.

# Histogram of Major options rating
results_model_3("cat_weighted_variance_score").plot(variety="hist")
Punkteverteilung. Bild vom Autor
exceptions = results_model_3(results_model_3("cat_weighted_variance_score")>=0.4)

print(f" There are {exceptions.form(0)} benchmark units with vital variance throughout the first options")

Bild vom Autor

Diese 18 Fälle müssen überprüft werden, um sicherzustellen, dass die Benchmark-Units related sind.

Wie Sie sehen, ist es uns mit ein paar Zeilen Code und etwas Verständnis der Nearest-Neighbor-Suche gelungen, interne Benchmark-Units festzulegen. Wir können die Units nun verteilen und beginnen, die KPIs der Resorts anhand ihrer Benchmark-Units zu messen.

Sie müssen sich nicht immer auf die modernsten Methoden des maschinellen Lernens konzentrieren, um Mehrwert zu erzielen. Sehr oft kann einfaches maschinelles Lernen großen Mehrwert liefern.

Welche Ziele können Sie in Ihrem Unternehmen leicht erreichen, indem Sie maschinelles Lernen einsetzen?

Weltbank. „World Improvement Indicators“. Abgerufen am 11. Juni 2024 von https://datacatalog.worldbank.org/search/dataset/0038117

Aggarwal, CC, Hinneburg, A., & Keim, DA (nd). Über das überraschende Verhalten von Distanzmetriken im hochdimensionalen Raum. IBM TJ Watson Analysis Middle und Institut für Informatik, Universität Halle. Abgerufen von https://bib.dbvis.de/uploadedFiles/155.pdf

SciPy v1.10.1 Handbuch. scipy.spatial.distance.minkowskiAbgerufen am 11. Juni 2024 von https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html

GeeksforGeeks. Haversine-Formel zur Ermittlung der Entfernung zwischen zwei Punkten auf einer Kugel. Abgerufen am 11. Juni 2024 von https://www.geeksforgeeks.org/haversine-formula-to-find-distance-between-two-points-on-a-sphere/

scikit-learn. Neighbors-Modul. Abgerufen am 11. Juni 2024 von https://scikit-learn.org/steady/modules/courses.html#module-sklearn.neighbors

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert