【问题标题】:Minimize distance using pandas dataframes and constraints (Knn)使用 pandas 数据框和约束 (Knn) 最小化距离
【发布时间】:2019-05-08 14:53:25
【问题描述】:

我第一次尝试使用 Scipy 和 Scipy 最小化。我已阅读文档并查看了一些 YT 教程,似乎每次我们需要最小化变量时,我们都需要编写手头问题的数学表示。

就我而言,我有一个代表我的数据集的玩具示例。我有:

  • 产品列表
  • 客户列表和关于他们是否购买产品的二元响应
  • 我正在尝试对我的客户进行分类的多个集群。存储的值表示集群的中心,在优化步骤之前它被设置为 0。

我所做的非常基础,对于每个集群,我都在计算每个集群值与客户交易之间的平方差的平方根。这样每个客户对每个集群都有一个距离值。

然后我为每个客户取最低距离值并总结它们。

  • 这个总距离是我想要最小化的总距离,这是我的目标
  • 决策变量在集群中全为 0,
  • 约束条件(Bound?),聚类中心应保持在 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()

我是否已经创建了许多不同的 DataFrame 以使其正常工作?

使用 Scipy.minimize 最小化总距离的正确方法是什么?

【问题讨论】:

  • Scipy 以外的解决方案也非常受欢迎,只要距离最小化。

标签: python pandas scipy statistics


【解决方案1】:

以下是您可以在 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

【讨论】:

  • 嘿@AILearning,感谢您抽出宝贵时间,我想我从概念上理解优化器函数在做什么,它将为函数提供决策变量。该函数将返回该值,优化器将在它达到最小值时运行。我有以下问题: - 它是逐步进行的吗?如果是这样,有没有办法设置步骤和迭代次数? - 这是本地/全局最小值吗?
  • 是的,我们可以使用 tol - 作为终止标准(这有助于驱动到全局最小值),在我们有 maxiter 的选项下,这将限制计算时间
  • 步骤怎么样?如果我们希望算法尝试使用 0.001 步收敛?
  • 是的,它是一个关键参数。使用 eps 来改变它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 2019-02-04
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
相关资源
最近更新 更多