Python 如何计算权重以最小化差异?

Python 如何计算权重以最小化差异?,python,matlab,optimization,variance,convex-optimization,Python,Matlab,Optimization,Variance,Convex Optimization,给定几个向量: x1 = [3 4 6] x2 = [2 8 1] x3 = [5 5 4] x4 = [6 2 1] 我想找到每个项目的权重w1,w2,w3,并得到每个向量的加权和:yi=w1*i1+w2*i2+w3*i3。例如,y1=3*w1+4*w2+6*w3 使这些值(y1、y2、y3、y4)的方差最小化 注意:w1,w2,w3应该>0,并且w1+w2+w3=1 我不知道应该是什么样的问题。。。如何用python或matlab求解 w = [5, 6, 7] x1 = [3, 4, 6

给定几个向量:

x1 = [3 4 6]
x2 = [2 8 1]
x3 = [5 5 4]
x4 = [6 2 1]
我想找到每个项目的权重w1,w2,w3,并得到每个向量的加权和:
yi=w1*i1+w2*i2+w3*i3
。例如,
y1=3*w1+4*w2+6*w3
使这些值(y1、y2、y3、y4)的方差最小化

注意:w1,w2,w3应该>0,并且
w1+w2+w3=1

我不知道应该是什么样的问题。。。如何用python或matlab求解

w = [5, 6, 7]
x1 = [3, 4, 6]
x2 = [2, 8, 1]
x3 = [5, 5, 4]
y1, y2, y3 = 0, 0, 0
for index, i in enumerate(w):
    y1 = y1 + i * x1[index]
    y2 = y2 + i * x2[index]
    y3 = y3 + i * x3[index]
print(min(y1, y2, y3))
我想我可能知道你的问题的目的。但是如果你想找到最小的值,我希望这能帮助你。
我只是将这些值设置为固定值,当您看到这是解决问题的一种方法时,您可以将其设置为
def

您可以从构建损失函数开始,说明方差和
w
的约束条件。平均值为
m=(1/4)*(y1+y2+y3+y4)
。然后方差为
(1/4)*((y1-m)^2+(y2-m)^2+(y3-m)^2+(y4-m)^2)
,约束为
a*(w1+w2+w3-1)
,其中
a
是拉格朗日乘数。在我看来,这个问题就像是一个带有凸约束的凸优化,因为损失函数对于目标变量(w1、w2、w3)是二次的,并且约束是线性的。您可以根据提供的约束查找投影梯度下降算法。看看这里,对于这类问题,通常没有直接的解析解。

我的完整解可以是

技巧是将向量
xi
作为矩阵
x
的列 然后将问题转化为一个凸问题,其解的约束在单位单纯形上

我用计算机解决了它。
我计算了目标函数的梯度,并创建了到目标函数的投影

现在只需迭代它们。
我使用验证了我的解决方案

%StackOverflow 44984132
%如何计算权重以最小化差异?
%备注:
%   1.  sa
%待办事项:
%   1.  ds
%发行说明
% - 1.0.000     08/07/2017
%*首次发布。
%%一般参数
运行('InitScript.m');
figureIdx=0;%=0
vW=ProjectSimplex(vW、simplexRadius、stopThr);
结束
disp(['']);
disp(['投影次梯度解-[',num2str(vW.'),']']);
%%恢复默认值
%设置(0,'DefaultFigureWindowStyle','normal');
%设置(0,'DefaultAxesLooseInset',defaultLoosInset);

您可以在中看到完整的代码(PDF也可用)。

我对优化问题不太了解,但我了解了梯度下降的概念,因此我尝试减少最大分数和最小分数之间的权重,我的脚本如下:

# coding: utf-8
import numpy as np
#7.72
#7.6
#8.26

def get_max(alist):
    max_score = max(alist)
    idx = alist.index(max_score)
    return max_score, idx

def get_min(alist):
    max_score = min(alist)
    idx = alist.index(max_score)
    return max_score, idx

def get_weighted(alist,aweight):
    res = []
    for i in range(0, len(alist)):
        res.append(alist[i]*aweight[i])
    return res

def get_sub(list1, list2):
    res = []
    for i in range(0, len(list1)):
        res.append(list1[i] - list2[i])
    return res

def grad_dec(w,dist, st = 0.001):
    max_item, max_item_idx = get_max(dist)
    min_item, min_item_idx = get_min(dist)
    w[max_item_idx] = w[max_item_idx] - st
    w[min_item_idx] = w[min_item_idx] + st

def cal_score(w, x):
    score = []
    print 'weight', w ,x
    for i in range(0, len(x)):
        score_i = 0
        for j in range(0,5):
            score_i = w[j]*x[i][j] + score_i
        score.append(score_i)
    # check variance is small enough
    print 'score', score
    return score

    # cal_score(w,x)

if __name__ == "__main__":
    init_w = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
    x = [[7.3, 10, 8.3, 8.8, 4.2], [6.8, 8.9, 8.4, 9.7, 4.2], [6.9, 9.9, 9.7, 8.1, 6.7]]
    score = cal_score(init_w,x)
    variance = np.var(score)
    round = 0
    for round in range(0, 100):
        if variance < 0.012:
            print 'ok'
            break
        max_score, idx = get_max(score)
        min_score, idx2 = get_min(score)
        weighted_1 = get_weighted(x[idx], init_w)
        weighted_2 = get_weighted(x[idx2], init_w)
        dist = get_sub(weighted_1, weighted_2)
        # print max_score, idx, min_score, idx2, dist
        grad_dec(init_w, dist)
        score = cal_score(init_w, x)
        variance = np.var(score)
        print 'variance', variance

    print score
#编码:utf-8
将numpy作为np导入
#7.72
#7.6
#8.26
def get_max(列表):
最高分数=最高(alist)
idx=列表索引(最大分数)
返回最大分数,idx
def get_min(列表):
最大分数=最小分数(alist)
idx=列表索引(最大分数)
返回最大分数,idx
def get_加权(列表,加权):
res=[]
对于范围(0,len(alist))中的i:
res.append(alist[i]*aweight[i])
返回res
def get_sub(列表1、列表2):
res=[]
对于范围(0,len(列表1))中的i:
res.append(list1[i]-list2[i])
返回res
def梯度dec(w,dist,st=0.001):
max\u item,max\u item\u idx=get\u max(dist)
最小项目,最小项目idx=获取最小(距离)
w[max\u item\u idx]=w[max\u item\u idx]-st
w[min_item_idx]=w[min_item_idx]+st
def校准分数(w,x):
分数=[]
打印“重量”,w,x
对于范围(0,len(x))中的i:
得分i=0
对于范围(0,5)内的j:
分数i=w[j]*x[i][j]+分数i
score.append(score_i)
#检查差异是否足够小
打印“分数”,分数
回击得分
#cal_分数(w,x)
如果名称=“\uuuuu main\uuuuuuuu”:
初始w=[0.2,0.2,0.2,0.2,0.2,0.2,0.2]
x=[[7.3,10,8.3,8.8,4.2],[6.8,8.9,8.4,9.7,4.2],[6.9,9.9,9.7,8.1,6.7]]
分数=校准分数(初始w,x)
方差=净现值(分数)
四舍五入=0
对于范围内的四舍五入(0,100):
如果方差小于0.012:
打印“ok”
打破
最大分数,idx=获取最大分数(分数)
最小分数,idx2=获取最小分数(分数)
加权_1=获得加权(x[idx],初始_w)
加权2=获得加权(x[idx2],初始w)
dist=get_sub(加权_1,加权_2)
#打印最大分数、idx、最小分数、idx2、距离
年级12月(初始w区)
分数=校准分数(初始w,x)
方差=净现值(分数)
打印“差异”,差异
打印分数

在我的实践中,它确实可以减少方差。我很高兴,但我不知道我的解在数学上是否可靠

y
-值的方差是多少?这些是固定值…重量有待确定。。。w1,w2,w3不是固定的。w1,…,上有约束吗。。。?如果不是将所有w都设置为零。是的,constriants补充道。看起来像是一个优化问题,所以可能是一种动态规划方法来获得精确解。否则,您可以尝试梯度下降65这是输出。谢谢!你真的理解我的问题,给我一个提示,你可以用投影次梯度法来解决它。看看我的答案。
# coding: utf-8
import numpy as np
#7.72
#7.6
#8.26

def get_max(alist):
    max_score = max(alist)
    idx = alist.index(max_score)
    return max_score, idx

def get_min(alist):
    max_score = min(alist)
    idx = alist.index(max_score)
    return max_score, idx

def get_weighted(alist,aweight):
    res = []
    for i in range(0, len(alist)):
        res.append(alist[i]*aweight[i])
    return res

def get_sub(list1, list2):
    res = []
    for i in range(0, len(list1)):
        res.append(list1[i] - list2[i])
    return res

def grad_dec(w,dist, st = 0.001):
    max_item, max_item_idx = get_max(dist)
    min_item, min_item_idx = get_min(dist)
    w[max_item_idx] = w[max_item_idx] - st
    w[min_item_idx] = w[min_item_idx] + st

def cal_score(w, x):
    score = []
    print 'weight', w ,x
    for i in range(0, len(x)):
        score_i = 0
        for j in range(0,5):
            score_i = w[j]*x[i][j] + score_i
        score.append(score_i)
    # check variance is small enough
    print 'score', score
    return score

    # cal_score(w,x)

if __name__ == "__main__":
    init_w = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
    x = [[7.3, 10, 8.3, 8.8, 4.2], [6.8, 8.9, 8.4, 9.7, 4.2], [6.9, 9.9, 9.7, 8.1, 6.7]]
    score = cal_score(init_w,x)
    variance = np.var(score)
    round = 0
    for round in range(0, 100):
        if variance < 0.012:
            print 'ok'
            break
        max_score, idx = get_max(score)
        min_score, idx2 = get_min(score)
        weighted_1 = get_weighted(x[idx], init_w)
        weighted_2 = get_weighted(x[idx2], init_w)
        dist = get_sub(weighted_1, weighted_2)
        # print max_score, idx, min_score, idx2, dist
        grad_dec(init_w, dist)
        score = cal_score(init_w, x)
        variance = np.var(score)
        print 'variance', variance

    print score