def evaluate_elm(elm_file, validation_file, batch_size):
    elm = ELM(np.zeros((0,0)), np.zeros((0,0)), inputs_normalized=True)
    elm.load(elm_file)

    data_file = h5py.File(validation_file, "r")

    timer = time.time()
    data = data_file['data']
    labels = data_file['labels']
    print("Data loaded", timeit(timer))

    timer = time.time()
    outer_batch_size = batch_size * 10  # How much can fit in memory at a time
    num_batches = int(math.ceil(float(data.shape[0]) / outer_batch_size))  # float division, round up

    skin_skin = 0
    skin_but_not_skin = 0
    not_skin_not_skin = 0
    not_skin_but_skin = 0

    for i in range(num_batches):
        start = i * outer_batch_size
        end = (i + 1) * outer_batch_size

        predicted_y = elm.predict(data[start: end], batch_size=batch_size)
        np.sign(predicted_y, out=predicted_y)

        current_index = 0
        
        label_batch = labels[start: end]
        for i in range(len(label_batch)):
            if label_batch[i] == 1 and predicted_y[current_index] == 1:
                skin_skin += 1
            elif label_batch[i] == -1 and predicted_y[current_index] == -1:
                not_skin_not_skin += 1
            elif label_batch[i] == -1 and predicted_y[current_index] == 1:  # not_skin_but_skin
                not_skin_but_skin += 1
            elif label_batch[i] == 1 and predicted_y[current_index] == -1:
                skin_but_not_skin += 1
            # else:
            #     print(label_batch[i], predicted_y[current_index])
            current_index += 1

    print("Finished prediction and analysis", timeit(timer))

    print("Neurons:")
    for neuron_function, num_neurons, weight_matrix, bias_vector in elm.neurons:
        print(neuron_function, num_neurons)
    print(len(labels), "data points")
    print("True-True:", skin_skin)
    print("False-False:", not_skin_not_skin)
    print("True-False:", skin_but_not_skin)
    print("False-True:", not_skin_but_skin)
    print("-" * 80)
def train_elm(filename, batch_size, neuron_allocation=None, inputs_normalized=False):
    if not neuron_allocation:
        neuron_allocation = {100: "sigm"}
    data_file = h5py.File(filename, "r")

    timer = time.time()
    data = data_file['data']
    labels = data_file['labels']
    print("Data loaded", timeit(timer))

    # accuracy_list = []
    # for i in range(5):
    timer = time.time()
    elm = ELM(data, labels, inputs_normalized)
    for key in neuron_allocation.keys():
        elm.add_neurons(neuron_allocation[key], key)
    elm.train()
    print("ELM trained!", timeit(timer))

    timer = time.time()
    predicted_y = elm.predict(data, batch_size=batch_size)
    print("ELM prediction finished", timeit(timer))
    np.sign(predicted_y, out=predicted_y)

    timer = time.time()
    num_batches = math.ceil(float(labels.shape[0]) / batch_size)  # float division, round up
    current_index = 0
    skin_skin = 0
    skin_but_not_skin = 0
    not_skin_not_skin = 0
    not_skin_but_skin = 0

    for label_batch in np.array_split(labels, num_batches):
        for i in range(len(label_batch)):
            if label_batch[i] == 1 and predicted_y[current_index] == 1:
                skin_skin += 1
            elif label_batch[i] == -1 and predicted_y[current_index] == -1:
                not_skin_not_skin += 1
            elif label_batch[i] == -1 and predicted_y[current_index] == 1: # not_skin_but_skin
                not_skin_but_skin += 1
            elif label_batch[i] == 1 and predicted_y[current_index] == -1:
                skin_but_not_skin += 1
            current_index += 1
    accuracy = float(skin_skin + not_skin_not_skin) / (skin_skin + not_skin_not_skin + skin_but_not_skin + not_skin_but_skin)
    print("Accuracy:", accuracy)
    print("Finished analyzing errors", timeit(timer))
    print(len(labels), "data points")
    print("True-True:", skin_skin)
    print("False-False:", not_skin_not_skin)
    print("True-False:", skin_but_not_skin)
    print("False-True:", not_skin_but_skin)
    # print(sum(accuracy_list) / len(accuracy_list))
    elm.save(data_file.filename[:data_file.filename.rindex('.')] + '.elm')
def load_elm(model_file):
    elm = ELM(np.zeros((0, 0)), np.zeros((0, 0)), inputs_normalized=True)
    elm.load(model_file)
    return elm