2013-04-18 9 views
10

私はいくつかのデータを持っており、共通の比率を維持する小さなグループに分割したいと思います。私は2つの配列の入力を受け取り、サイズ比を計算し、いくつのグループを分けることができるかを教えてくれる関数を書いた(すべてのグループが同じサイズの場合)、ここに関数がある:Python関数でデータを分割するときの比率を維持する

def cross_validation_group(train_data, test_data): 
    import numpy as np 
    from calculator import factors 
    test_length = len(test_data) 
    train_length = len(train_data) 
    total_length = test_length + train_length 
    ratio = test_length/float(total_length) 
    possibilities = factors(total_length) 
    print possibilities 
    print possibilities[len(possibilities)-1] * ratio 
    super_count = 0 
    for i in possibilities: 
     if i < len(possibilities)/2: 
      pass 
     else: 
      attempt = float(i * ratio) 
      if attempt.is_integer(): 
       print str(i) + " is an option for total size with " + str(attempt) + " as test size and " + str(i - attempt) + " as train size! This is with " + str(total_length/i) + " folds." 
      else: 
       pass 
    folds = int(raw_input("So how many folds would you like to use? If no possibilities were given that would be sufficient, type 0: ")) 
    if folds != 0: 
     total_size = total_length/folds 
     test_size = float(total_size * ratio) 
     train_size = total_size - test_size 
     columns = train_data[0] 
     columns= len(columns) 
     groups = np.empty((folds,(test_size + train_size),columns)) 
     i = 0 
     a = 0 
     b = 0 
     for j in range (0,folds): 
      test_size_new = test_size * (j + 1) 
      train_size_new = train_size * j 
      total_size_new = (train_size + test_size) * (j + 1) 
      cut_off = total_size_new - train_size 
      p = 0 
      while i < total_size_new: 
       if i < cut_off: 
        groups[j,p] = test_data[a] 
        a += 1 
       else: 
        groups[j,p] = train_data[b] 
        b += 1 
       i += 1 
       p += 1 
     return groups 
    else: 
     print "This method cannot be used because the ratio cannot be maintained with equal group sizes other than for the options you were givens" 

私の質問は、各グループが同じ量を持っていることを確認するために繰り返すのではなく、折り返しの数と関数を変更する関数への3番目の入力適切な比率で、それはちょうど良い比率を持っていますが、サイズが異なりますか? @JamesHolderness

ため

添加は、だからあなたの方法はほぼ完璧ですが、ここで問題の1つである:9つの折り目と長さ357と143との

、これは返すリストです:

[(39, 16), (39, 16), (39, 16), (39, 16), (39, 16), (39, 16), (39, 16), (39, 16), (39, 16)] 

今すぐ列を追加すると、次のようになります。351 144

3 51は357よりも小さいので問題ありませんが、143より大きいため144は機能しません!その理由は、357と143は配列の長さなので、その配列の144番目の行は存在しません...

+0

さまざまなトレーニングセットと相互検証することを意味しますか?これは統計的にはまあまあですか?それは実際には通常行われますか? – thebigdog

+0

はい、これは相互検証のためのものです。いいえ、これは、トレーニングデータにないテストデータに何かが存在するかどうかを確認するために、テストセットとトレーニングセットの類似性をテストすることになっています。通常、クロスバリデーションは1つのトレーニングセットでのみ実行され、2つのアレイではなく、トレーニングアレイとトレーニングアレイに列を与えて、そうすることができます。 –

+1

2つの配列の大きさがmとnで、mのnで割った既約分数がp/qの場合、m = k * pとn = k * q '。一度あなたが 'k'を持っていれば、それの任意の[パーティション](http://en.wikipedia.org/wiki/Partition_(number_theory))は要素の比率を保持する元のデータの分割につながります。あなたが私が精緻化する必要があるかどうかを教えてください。 – Jaime

答えて

3

私はあなたのために働くかもしれないと思うアルゴリズムはここにあります。

あなたはtest_lengthとtrain_lengthを取ってGCDで割って比率を単純な割合として求めます。あなたは分子と分母を取り、それを一緒に追加します。これがあなたのグループのサイズ係数です。例えば

比が3:2の場合は、各グループのサイズは、次にtotal_lengthを取るための理想的なサイズを取得するために折り目の数で割り5

の倍数でなければなりません第1のグループは浮動小数点数でもよい。あなたは5以下の最大倍数を見つけます。これはあなたの最初のグループです。

合計からその値を引き、次のグループの理想的なサイズを得るためにfoldds-1で割ります。再び5の最大倍数を求め、合計から減算し、すべてのグループを計算するまで続行します。

いくつかのコード例:これは、各グループ(テストや電車)が、我々はあまりにも多く、最初は使用している場合、心配しないで使用されるサイズを追跡するように更新されました

total_length = test_length + train_length   
divisor = gcd(test_length,train_length) 
test_multiple = test_length/divisor 
train_multiple = train_length/divisor 
total_multiple = test_multiple + train_multiple 

# Adjust the ratio if there isn't enough data for the requested folds 
if total_length/total_multiple < folds: 
    total_multiple = total_length/folds 
    test_multiple = int(round(float(test_length)*total_multiple/total_length)) 
    train_multiple = total_multiple - test_multiple 

groups = [] 
for i in range(folds,0,-1): 
    float_size = float(total_length)/i 
    int_size = int(float_size/total_multiple)*total_multiple 
    test_size = int_size*test_multiple/total_multiple 
    train_size = int_size*train_multiple/total_multiple 
    test_length -= test_size # keep track of the test data used 
    train_length -= train_size # keep track of the train data used 
    total_length -= int_size 
    groups.append((test_size,train_size)) 

# If the test_length or train_length are negative, we need to adjust the groups 
# to "give back" some of the data. 
distribute_overrun(groups,test_length,0) 
distribute_overrun(groups,train_length,1) 

最後に、オーバーランがある場合(つまり、test_lengthまたはtrain_lengthが負になりました)、オーバーランをゼロに戻すのに必要な数の項目で比率の適切な側をデクリメントして、グループにオーバーランを戻します。

distribute_overrun機能が以下に含まれています。

def distribute_overrun(groups,overrun,part): 
    i = 0 
    while overrun < 0: 
     group = list(groups[i]) 
     group[part] -= 1 
     groups[i] = tuple(group) 
     overrun += 1 
     i += 1 

最後に、グループは、各グループのtest_sizeとtrain_sizeを含むタプルのリストになります。

あなたが望むもののように聞こえるが、コード例を拡張する必要がある場合は、私に知らせてください。

+0

ほぼ完璧な!ほとんどの状況で素晴らしい、 ssueは、端数を単純化できない場合、最後のものを除いてすべてのタプルを '(0,0)'として返します。元の数だけです。比率がそれほど不可能な場合、比率を少し壊すような機能に追加できることはありますか? –

+0

も ​​'total_length = train_length + test_length'を先頭に追加しました。あなたは' total_length'を定義しませんでした。 –

+0

元のコードから 'total_length'を使っていましたが、明確にするために例に追加しました。十分なデータがない場合、比率を調整するためのいくつかの追加コードで回答を更新しました。私はあなたのデータが要求された折り畳みの数によって均等に分割されないならば、最後にいくつかのデータを残すことにします。 –

3

別の質問で、著者はあなたと同様の相互検証をしたかったのです。してください、​​。あなたはtrain_datatest_dataで定義された間隔に対応する必要があります

import numpy as np 
# in both train_data the first line is used for the cross-validation, 
# and the other lines will follow, so you can add as many lines as you want 
test_data = np.array([ 0., 1., 2., 3., 4., 5.]) 
train_data = np.array([[ 0.09, 1.9, 1.1, 1.5, 4.2, 3.1, 5.1], 
         [ 3, 4, 3.1, 10, 20, 2, 3]]) 

def cross_validation_group(test_data, train_data): 
    om1,om2 = np.meshgrid(test_data,train_data[0]) 
    dist = (om1-om2)**2 
    indexes = np.argsort(dist, axis=0) 
    return train_data[:, indexes[0]] 

print cross_validation_group(test_data, train_data) 
# array([[ 0.09, 1.1 , 1.9 , 3.1 , 4.2 , 5.1 ], 
#  [  3 , 3.1 ,  4 ,  2 , 20 ,  3 ]]) 

:あなたの問題への答えを働いて、それは次のようになります。

+0

これはまったく私が望むものではありません...私のグループ分けは、このようなものでうまくいきますが、配列のためのグループの量となる別の変数を取る関数が必要です。トレーニングデータからテストデータまでの比率が同じであれば違います。 –

+0

私はあなたの意見を忘れてしまったと思います。これはさまざまなサイズで動作しますが、あなたが与えるtest_dataによって制御されるグループの量を示す変数はありません。 –

+0

基本的に私は別の変数xが必要です。ここでx =グループの数です。行は異なる可能性がありますが、各グループでは、test_dataと行の比率が同じでなければなりません。この方法では、クロスバリデーションに偏りはありません。 –

関連する問題