19 déc. 2024

[Dynamo += Python] la similarité cosinus

 



Explication de la similarité cosinus et un exemple d'application dans Dynamo

#DynamoBIM #Python #Vecteurs #AutodeskExpertElite #AutodeskCommunity 

if this article is not in your language, use the Google Translate widget ⬈ (bottom of page for Mobile version )



La similarité cosinus est une mesure de similarité entre deux vecteurs dans un espace multidimensionnel. Elle se base sur l'angle entre ces vecteurs, et non sur leur magnitude (taille). 

Elle est couramment utilisée en traitement du langage naturel (NLP), apprentissage automatique, et recherche d'information pour comparer des documents ou des représentations vectorielles.

Cela en fait une métrique idéale pour comparer des orientations avec précision sur des grandes distances.


  • Définition Mathématique

La formule de la similarité cosinus entre deux vecteurs 𝑎  et  𝑏 est donnée par :



  • Interprétation Géométrique

La similarité cosinus se concentre sur l’angle entre deux vecteurs dans un espace vectoriel :

  • Si cos(θ)=1 : Les vecteurs pointent exactement dans la même direction.
  • Si cos(θ)=0 : Les vecteurs sont orthogonaux (aucune corrélation directionnelle).
  • Si cos(θ)=1 : Les vecteurs pointent dans des directions opposées.


Voici le contexte dans Dynamo

Nous avons un ensemble de points et nous souhaitons obtenir seulement les points alignés (surlignés en jaune) avec le vecteur (en gris).


le code Python


import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

    
def cosine_similarity(point, vector):
    """
    Calculate cosine similarity between a point (treated as vector) and the direction vector.
    - param point: Point (converted to vector).
    - param vector: Direction vector (Vector).
    - return: Cosine similarity value.
    """
    dot_product = point.AsVector().Dot(vector)
    mag_point = point.AsVector().Length
    mag_vector = vector.Length
    
    # Avoid division by zero
    if mag_point == 0 or mag_vector == 0:
        return 0
    
    return dot_product / (mag_point * mag_vector)
    
lstPts = IN[0]
vector = IN[1]

# get aligned points with vectors with Dynamo DesignScript API
points_align_with_vector = [point for point in lstPts if abs(cosine_similarity(point, vector.Normalized())) > 0.9999 ]
# get similarities values for debug
# similarities = [(cosine_similarity(point, vector.Normalized()), point) for point in lstPts]
sorted_points = sorted(points_align_with_vector, key = lambda p : p.AsVector().Dot(vector.Normalized()))

OUT = sorted_points
. .


Mais pourquoi ne pas utiliser simplement le produit scalaire (ou vectoriel) de deux vecteurs normalisés ❓❓

Bien que le produit scalaire des vecteurs normalisés soit mathématiquement équivalent à la similarité cosinus, dans la pratique, normaliser systématiquement les vecteurs présente des inconvénients :

  • Normaliser des vecteurs peut être coûteux si ceux-ci sont très grands ou nombreux
  • En normalisant les vecteurs, on perd la notion de magnitude ou d'importance du vecteur.

La similarité cosinus préserve la notion de direction tout en restant robuste aux différences de magnitude (ce qui peut être avantageux lorsque l'on recherche de la précision sur des grandes distances).

Cependant, une fois les points alignés avec le vecteur obtenus, un produit scalaire (non normalisé) pourra être utile pour trier les points.

Exemple triage de point suivant un vecteur


Exemple triage de point suivant un vecteur opposé




Je vous souhaite de Bonnes fêtes de fin d'années à tous


je termine par un petit clin d'œil à mes confrères Experts Élite qui liront cet article 😄





0 commentaires:

Enregistrer un commentaire