Минимизируйте расстояние, используя рамки данных pandas и ограничения (Knn) - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь впервые использовать Сципи и Сципи свести к минимуму.Я прочитал документацию и увидел несколько учебных пособий по YT. Кажется, что каждый раз, когда нам нужно минимизировать переменную, нам нужно написать математическое представление проблемы.

В моем случае у меня есть игрушечный пример, который представляет мойнабор данных.У меня есть:

  • список продуктов
  • список клиентов и бинарный ответ о том, купили они продукт или нет
  • количество кластеров, которыми я являюсьпытаясь классифицировать моих клиентов с.Сохраненное значение представляет центр кластера, перед этапом оптимизации он устанавливается равным 0.

То, что я делаю, довольно просто, для каждого кластера я вычисляю квадратный корень квадратной разности между каждымстоимость кластера и клиентские транзакции.Чтобы у каждого клиента было значение расстояния для каждого кластера.

Затем я беру для каждого клиента наименьшее значение расстояния и суммирую их.

  • Это общее количество, которое я хочу минимизировать, это моя цель
  • Переменные решения - это все 0 в кластере,
  • ограничения (Связано?), центр кластеров должен оставаться в пределах 0,00 и 1,00

Поскольку я использую exp, функция не линейна, поэтому я использую SLSQP, и мое дикое предположение было попробовать это:

sol = minimize(total_distance_to_minimize,   dataframe[clusters.keys()], method='SLSQP', Bounds=((0,1)), options={'disp'=True})

на следующем примере с игрушкой:

#utf8
import pandas as pd
import numpy as np
from scipy.optimize import minimize, Bounds
import math

#dict holoding distances between customers and clusters
distances = dict()

product_list = ['banana juice','pinnaple juice' ,
'maracudja',
'cupuacu',
'goava',
'coconut',
'apple',
'grappe',
'acai']

customer_dict = {'Bilbon Saquet' :[0,1,0,1,0,1,0,0,0],
'Gandalft':[0,0,0,1,0,0,0,0,0],
'Thorin':[1,1,1,0,0,0,0,0,0],
'Smaug':[0,0,1,1,0,1,0,0,1],
'Radagast':[0,1,1,1,1,1,0,0,0],
'Elrond':[0,0,0,1,0,1,1,0,1],
'Balin':[0,0,0,0,0,1,0,0,0]}

clusters =  {'Clusters 1' :[0,0,0,0,0,0,0,0,0],
'Clusters 2':[0,0,0,0,0,0,0,0,0],
'Clusters 3':[0,0,0,0,0,0,0,0,0],
'Clusters 4':[0,0,0,0,0,0,0,0,0]}

data = pd.DataFrame(customer_dict, index= product_list)
clusters = pd.DataFrame(clusters, index=product_list)

dataframe = pd.concat([data, clusters], axis='columns')

for k in clusters :
    for customer in customer_dict:
        distances.setdefault(customer, [])
        distances[customer].append(math.sqrt(((dataframe[k]-dataframe[customer])**2).sum()))

distances = pd.DataFrame(distances, index=clusters.keys())
total_distance_to_minimize = distances.min().sum()

Может быть, я создал много разных фреймов данных для того, чтобы это работало?

Каков будет правильный способиспользуя Scipy.minimize, чтобы минимизировать это общее расстояние?

1 Ответ

0 голосов
/ 10 декабря 2018

Вот шаги, с помощью которых вы можете использовать функцию минимизации в scipy для решения проблемы.

Переменные решения должны быть одномерным массивом.Следовательно, я сглаживаю ваши переменные решения как

init_vars = np.zeros(len(product_list)*clusters.shape[1])

Необходимо определить целевую функцию, которая должна быть передана в оптимизатор как вызываемая функция.

def obj_fn(dec_vars):
    distances={}
    temp_clusters = pd.DataFrame(dec_vars.reshape((len(product_list),clusters.shape[1])),
                                 index=product_list,columns= clusters.columns)

    temp_df= pd.concat([data, temp_clusters], axis='columns')
    for k in clusters :
        for customer in customer_dict:
            distances.setdefault(customer, [])
            distances[customer].append(math.sqrt(((temp_df[k]-temp_df[customer])**2).sum()))

    distances = pd.DataFrame(distances, index=clusters.keys())
    return distances.min().sum() 

Теперь мыдолжны установить границы для каждой переменной решения в последовательном порядке.Собирая все воедино, мы будем использовать функцию оптимизатора следующим образом:

sol = minimize(obj_fn, init_vars , method='SLSQP', bounds=[(0,1) for _ in init_vars],tol =0,options={'maxiter':50,'eps':0.01})

. Для данного примера оптимальное решение, которое дает решатель:

5.562980209812645

Решение можно получить по выводу

dec_vars = sol.x
temp_clusters = pd.DataFrame(dec_vars.reshape((len(product_list),clusters.shape[1])),
                             index=product_list,columns= clusters.columns)

temp_df= pd.concat([data, temp_clusters], axis='columns')
print(temp_df)

:

                Balin  Bilbon Saquet  Elrond  Gandalft  Radagast  Smaug  \
banana juice        0              0       0         0         0      0   
pinnaple juice      0              1       0         0         1      0   
maracudja           0              0       0         0         1      1   
cupuacu             0              1       1         1         1      1   
goava               0              0       0         0         1      0   
coconut             1              1       1         0         1      1   
apple               0              0       1         0         0      0   
grappe              0              0       0         0         0      0   
acai                0              0       1         0         0      1   

                Thorin  Clusters 1    Clusters 2    Clusters 3    Clusters 4  
banana juice         1    0.685121  3.964158e-16  2.464523e-03  1.663972e-01  
pinnaple juice       1    1.000000  9.976724e-01  7.504636e-03  4.644470e-01  
maracudja            1    1.000000  9.972195e-01  7.066747e-01  1.774573e-01  
cupuacu              0    1.000000  9.959170e-01  9.999912e-01  5.891786e-01  
goava                0    0.993446  9.963349e-01  3.898192e-04  1.606294e-02  
coconut              0    1.000000  9.957576e-01  9.999994e-01  5.877336e-01  
apple                0    0.996145  1.676883e-16  2.963329e-01  2.001538e-02  
grappe               0    0.000000  2.918387e-16  2.711116e-18  1.562419e-17  
acai                 0    0.995514  1.584998e-16  9.947202e-01  1.472500e-02
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...