2014-02-03 1 views
1

Использование Python 2.7.6 и Pybrain 0,3 ...Почему splitWithProportion меняет количество в каждом наборе всякий раз, когда он вызывается?

Вот функция, я написал, чтобы создать набор данных для подготовки моей нейронной сети.

Это sequential data set и я хочу 75% от него будет подготовка тестовых данных данных и 25% (я считаю, что это общепринятый разумное разделение):

from pybrain.datasets import SequentialDataSet 

def create_data_sets(rows): 

    ds = SequentialDataSet(13, 1) 
    last_id = -1 
    count = 0 

    for row in rows: 

     current_id = int(row[14]) 
     if current_id != last_id: 
      count += 1 
      ds.newSequence() 
     last_id = current_id 

     ds.appendLinked(
      [int(row[0])/10000.0, 
      int(row[1])/10000.0, 
      int(row[2])/20.0, 
      int(row[3])/9.0, 
      int(row[4])/9.0, 
      int(row[5])/6.0, 
      int(row[6])/6.0, 
      float(row[7]), 
      float(row[8]), 
      float(row[9]), 
      float(row[10]), 
      int(row[11])/6.0, 
      int(row[12])/6.0], 
      [float(row[13])]) 

    test_data, train_data = ds.splitWithProportion(0.25)   
    return (test_data, train_data, count) 

Теперь я называю эту функцию в два раза, с одни и те же данные, как так (прикрывали запрос, так как имена таблиц и столбцов немного чувствительны, извините):

import sqlite3 

connection = sqlite3.connect('database.sqlite') 
cursor = connection.cursor() 
cursor.execute('select A,B,C,D,E,F,G,H,I,J,K,L,M,N,O from P order by O,A') 
rows = cursor.fetchall() 
connection.close() 

test_data, train_data, count = create_data_sets(rows) 
print str(len(test_data)) + " " + str(len(train_data)) + " " + str(count) 

test_data, train_data, count = create_data_sets(rows) 
print str(len(test_data)) + " " + str(len(train_data)) + " " + str(count) 

Глядя на выходе я получаю это (на самом деле, каждый раз, когда я запускаю его, оно меняется) :

400 1222 203 
386 1236 203 

Это меня смущает - почему он каждый раз разбивает данные по-разному?

Поскольку порядок набора данных не меняется, я бы ожидал, что он будет делать то же самое каждый раз, когда я его назову. Здесь какая-то магия?


Update

Вот другой, более простой, пример:

from pybrain import datasets 

d = datasets.SequentialDataSet(0, 1) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 

for _ in range(2): 
    test, train = d.splitWithProportion(0.25) 
    print str(len(test)) + " " + str(len(train)) 

я иногда получаю выход

5 18 
6 17 

Кажется, что каждый раз, когда splitWithProportion называют его можно круглый наборы по-разному, поэтому я предполагаю, что i t должно быть рандомизация последовательностей или что-то еще - как вы можете видеть, я не корректирую данные. Я в замешательстве, почему это нужно сделать.

ответ

0

Я считаю, что ваша проблема имеет что-то делать с тем, как вы создаете новые последовательности

 if current_id != last_id: 
     count += 1 
     ds.newSequence() 

Я проверил, что следующие последовательные возвращает результаты «6 18» каждый раз, когда он называется.

from pybrain import datasets 

d = datasets.SequentialDataSet(0, 1) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.newSequence() 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
d.addSample([],[0]) 
d.addSample([],[1]) 
test, train = d.splitWithProportion(0.25) 
print str(len(test)) + " " + str(len(train)) 

EDIT: Помнить с SequentialDataSet, что раскол по не последовательности отдельных образцов. Таким образом, с 4 последовательностями раскол 0,25 даст ровно 1 последовательность для теста и 3 последовательности для обучения. Если последовательности не имеют одинаковой длины, тогда вы получите разные результаты len() для теста и тренировки. Все работает как ожидалось для последовательного набора данных.

+0

Спасибо за ответ. Однако ваши последовательности имеют одинаковый размер (по 6 в каждом). Если вы измените их немного, вы также увидите это явление. Я добавил версию вашего кода в качестве примера на мой вопрос, чтобы вы могли видеть – kmp

+0

Я разъяснил ответ, теперь должен иметь смысл. – Firestrand

+0

Спасибо - я понимаю, что я получил бы 1 для теста и 3 для обучения в наборе с 4 последовательностями и, конечно, из-за округления, если множество не делится на 4, я ожидал бы всего целого числа последовательностей в два набора, но вопрос, который я пытаюсь задать, хотя и плохо, я думаю (извините), почему это не последовательно одни и те же последовательности в разделенных наборах данных - обратите внимание, что я просто вызываю splitWithProportion дважды на точно таком же наборе данных, и все же размер двух результирующих множеств меняется. Я думаю, там должна быть какая-то случайность, но я не понимаю, зачем это нужно. – kmp