Python 使用数据帧和约束(Knn)最小化距离
我第一次尝试使用Scipy和Scipy最小化。我已经阅读了文档和一些YT教程,似乎每次我们需要最小化一个变量时,我们都需要为手头的问题编写一个数学表示 在我的例子中,我有一个表示我的数据集的玩具示例。我有:Python 使用数据帧和约束(Knn)最小化距离,python,pandas,scipy,statistics,Python,Pandas,Scipy,Statistics,我第一次尝试使用Scipy和Scipy最小化。我已经阅读了文档和一些YT教程,似乎每次我们需要最小化一个变量时,我们都需要为手头的问题编写一个数学表示 在我的例子中,我有一个表示我的数据集的玩具示例。我有: 产品清单 客户列表和他们是否购买产品的二进制响应 我正在尝试对我的客户进行分类。存储的值表示群集的中心,在优化步骤之前,将其设置为0 我所做的是非常基本的,对于每个集群,我计算每个集群值和客户事务之间的平方差的平方根。因此,每个客户都有每个集群的距离值 然后,我为每个客户取最小距离值,并
- 产品清单
- 客户列表和他们是否购买产品的二进制响应
- 我正在尝试对我的客户进行分类。存储的值表示群集的中心,在优化步骤之前,将其设置为0
- 这是我想最小化的总距离,这是我的目标
- 决策变量都是群集中的0
- 约束(绑定?),簇中心应保持在0.00和1.00之间
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来最小化总距离的正确方法是什么?以下是使用Scipy中的minimizer函数解决问题的步骤 决策变量必须是一维数组。因此,我将您的决策变量展平为
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
只要距离最小化,Scipy以外的解决方案也非常受欢迎。嘿@Ailerning,谢谢你的时间,我想我从概念上理解了optimizer函数在做什么,它将为函数提供决策变量。函数将返回值,优化器将在达到最小值时运行。我有以下问题:-它是逐步进行的吗?如果是,是否有办法设置步骤和迭代次数这是局部/全局最小值吗?是的,我们可以使用tol-作为终止标准(这有助于驱动到全局最小值),在选项下我们有maxiter,这将限制计算时间。步骤如何?如果我们想让算法用0.001的步长收敛,是的,这是一个循环参数。使用eps进行更改。