Замена for-l oop лучшими альтернативами в пандафреймах для измерения сходства - PullRequest
1 голос
/ 06 февраля 2020

Я работаю над созданием функции, которая будет вычислять косинусное сходство каждой записи в наборе данных (измерение MxK) с записями в другом наборе данных (измерение NxK), где N намного меньше, чем M.

Приведенный ниже код хорошо работает, когда я тестирую его на крошечном наборе данных (например, на наборе данных «iris»). Я беспокоюсь, что это может помешать, когда у меня большие наборы данных (100K записей и более 100 переменных).

Я знаю, что для l oop не рекомендуется для такого сценария ios, и в этом случае я получил два цикла for. Мне интересно, может ли кто-нибудь предложить способы улучшения этого кода.

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

def similarity_calculation(seed_data, pool_data):
    # Create an empty dataframe to store the similarity scores
    similarity_matrix = pd.DataFrame()
    for indexi, rowi in pool_data.iterrows():
        # Create an array to score similarity score for each record in pool data
        similarity_score_array = []
        for indexj, rowj in seed_data.iterrows():
            # Fetch a single record from pool dataset
            pool = rowi.values.reshape(1, -1)
            # Fetch a single record from seed dataset
            seed = rowj.values.reshape(1, -1)
            # Measure similarity score between the two records
            similarity_score = (cosine_similarity(pool, seed))[0][0]
            similarity_score_array.append(similarity_score)
        # Append the similarity score array as a new record to the similarity matrix
        similarity_matrix = similarity_matrix.append(pd.Series(similarity_score_array), ignore_index=True)

Edit1 : Пример данных Набор данных iris используется следующим образом

iris_data = pd.read_csv("iris_data.csv", header=0)
# Split the data into seeds and pool sets, excluding the species details
seed_set = iris_data.iloc[:10, :4]
pool_set = iris_data.iloc[10:, :4]

Ожидаемый результат: enter image description here

Мой новый компактный код (с одним для l oop) выглядит следующим образом

def similarity_calculation_compact(seed_data, pool_data):
    Array1 = pool_data.values
    Array2 = seed_data.values
    scores = []
    for i in range(Array1.shape[0]):
        scores.append(np.mean(cosine_similarity(Array1[None, i, :], Array2)))
    final_data = pool_data.copy()
    final_data['mean_similarity_score'] = scores
    final_data = final_data.sort_values(by='mean_similarity_score', ascending=False)
    return(final_data)

Выход I получаю enter image description here

Я ожидал идентичных результатов, поскольку обе функции должны извлекать записи из данных пула, наиболее похожих (с точки зрения среднего косинусного сходства), на начальные данные.

1 Ответ

1 голос
/ 07 февраля 2020

Нет необходимости в циклах for, поскольку cosine_similarity принимает в качестве входных данных два массива фигур (n_samples_X, n_features) и (n_samples_Y, n_features) и возвращает массив формы (n_samples_X, n_samples_Y), вычисляя косинусное сходство между каждой парой двух входные массивы.

import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

iris_data = pd.read_csv("iris.csv", header=0)

seed_set = iris_data.iloc[:10, :4]
pool_set = iris_data.iloc[10:, :4]

np.mean(cosine_similarity(pool_set, seed_set), axis=1)

Результат (после сортировки):

array([0.99952255, 0.99947777, 0.99947545, 0.99946886, 0.99946596, ...])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...