2017-10-06 130 views
0

不確定如何繼續。我有一個數字列表(精確數字列表),但這些數字有一個模糊性:x,x + 1和x-1對我來說是完全一樣的。但是,我想通過更改元素來最小化列表的差異。這是我認爲到目前爲止(帶我知道這是行不通的樣本名單):最小化方差python

import numpy as np 
from scipy import stats 

lst = [0.474, 0.122, 0.0867, 0.896, 0.979] 
def min_var(lst): 
    mode = np.mean(lst) 
    var = np.var(lst) 
    result = [] 
    for item in list(lst): 
     if item < mean: # not sure this is a good test 
      new_item = item + 1 
     elif item > mean: 
      new_item = item - 1 
     else: 
      new_item = item 
     new_list = [new_item if x==item else x for x in lst] 
     new_var = np.var(new_list) 
     if new_var < var: 
      var = new_var 
      lst = new_list 
    return lst 

什麼功能的作用是增加1到3元。但是,當您從第4個和第5個減去1時,會出現最小差異。發生這種情況是因爲我在每個項目之後最小化了方差,而不允許進行多項更改。我怎麼能實現多個變化,最好是不看所有可能的解決方案(3 **如果我沒有弄錯)? 非常感謝

+0

你基本上要儘量減少'VAR((X +增量)%1)',其中X是你的一系列價值觀。嘗試使用像scipy.optimize這樣的數值求解器。最後,您希望數字的最佳範圍是從「delta」到「delta + 1」,您可以添加和刪除數字中的整數,以確保它們都在該範圍內。 –

+0

我錯在使用'scipy.optimize',但我寫了一個可以工作的解決方案。 –

回答

0

你可以認爲這是最小化var((x + delta) % 1)找到delta的一個問題,即x你的價值觀的陣列。然後你從你的值中加減整數,直到它們位於delta - 1 <= x[i] < delta的範圍內。這不是delta的連續函數,所以不能像scipy.optimize那樣使用求解器。但是,我們可以使用var((x + delta) % 1)的值僅在x的每個值處發生變化的信息,這意味着我們只需要測試x中的每個值作爲可能的delta,並找到最小化方差的值。

import numpy as np 

x = np.array([0.474, 0.122, 0.0867, 0.896, 0.979]) 

# find the value of delta 
delta = x[0] 
min_var = np.var((x - delta) % 1) 
for val in x: 
    current_var = np.var((x - val) % 1) 
    if current_var < min_var: 
     min_var = current_var 
     delta = val 

print(delta) 

# use `delta` to subtract and add the right integer from each value 
# we want values in the range delta - 1 <= val < delta 
for i, val in enumerate(x): 
    while val >= delta: 
     val -= 1. 
    while val < delta - 1.: 
     val += 1. 
    x[i] = val 

print(x) 

對於這個例子,它發現的[ 0.474 0.122 0.0867 -0.104 -0.021 ]0.0392方差的期望的解決方案。

+0

這似乎工作,謝謝。從來沒有這樣想過這個問題 – bernie

0

爲避免每次計算新變量(O(n²)),您可以看到當影響從xx+u的項目時,var會受到影響,如u*(u/2+x-m-u/n)

因此,這裏是一個準線性時間的解決方案:

l=np.array([0.474, 0.122, 0.0867, 0.896, 0.979]) 
l.sort() 
n=len(l) 
m=np.mean(l) 
print(l,np.var(l)) 
u=1 # increase little terms 

for i in range(n): 
    if u*(u/2+l[i]-m-u/n) < 0: 
     l[i]= l[i] + u 
     m = m+u/n # mean evolution 
    else: u = -1 # decrease big terms 

print(l,np.var(l)) 

和運行:

[ 0.0867 0.122 0.474 0.896 0.979 ] 0.1399936064 
[ 1.0867 1.122 1.474 0.896 0.979 ] 0.0392256064