1

Я пытаюсь использовать глубокую нейронную сетевую архитектуру для классификации по значению двоичной метки - 0 и +1. Вот мой код, чтобы сделать это в тензорном потоке. Кроме того, этот вопрос несет вперед от обсуждения в previous questionИзменение значения точности и отсутствие изменения значения потерь в двоичной классификации с использованием Tensorflow

import tensorflow as tf 
import numpy as np 
from preprocess import create_feature_sets_and_labels 

train_x,train_y,test_x,test_y = create_feature_sets_and_labels() 

x = tf.placeholder('float', [None, 5]) 
y = tf.placeholder('float') 

n_nodes_hl1 = 500 
n_nodes_hl2 = 500 
# n_nodes_hl3 = 500 

n_classes = 1 
batch_size = 100 

def neural_network_model(data): 

    hidden_1_layer = {'weights':tf.Variable(tf.random_normal([5, n_nodes_hl1])), 
         'biases':tf.Variable(tf.random_normal([n_nodes_hl1]))} 

    hidden_2_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])), 
         'biases':tf.Variable(tf.random_normal([n_nodes_hl2]))} 

    # hidden_3_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])), 
    #     'biases':tf.Variable(tf.random_normal([n_nodes_hl3]))} 

    # output_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])), 
    #     'biases':tf.Variable(tf.random_normal([n_classes]))} 

    output_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl2, n_classes])), 
        'biases':tf.Variable(tf.random_normal([n_classes]))} 


    l1 = tf.add(tf.matmul(data, hidden_1_layer['weights']), hidden_1_layer['biases']) 
    l1 = tf.nn.relu(l1) 

    l2 = tf.add(tf.matmul(l1, hidden_2_layer['weights']), hidden_2_layer['biases']) 
    l2 = tf.nn.relu(l2) 

    # l3 = tf.add(tf.matmul(l2, hidden_3_layer['weights']), hidden_3_layer['biases']) 
    # l3 = tf.nn.relu(l3) 

    # output = tf.transpose(tf.add(tf.matmul(l3, output_layer['weights']), output_layer['biases'])) 
    output = tf.add(tf.matmul(l2, output_layer['weights']), output_layer['biases']) 
    return output 



def train_neural_network(x): 
    prediction = tf.sigmoid(neural_network_model(x)) 
    cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(prediction, y)) 
    optimizer = tf.train.AdamOptimizer().minimize(cost) 

    hm_epochs = 10 

    with tf.Session() as sess: 
     sess.run(tf.initialize_all_variables()) 

     for epoch in range(hm_epochs): 
      epoch_loss = 0 
      i = 0 
      while i < len(train_x): 
       start = i 
       end = i + batch_size 
       batch_x = np.array(train_x[start:end]) 
     batch_y = np.array(train_y[start:end]) 

     _, c = sess.run([optimizer, cost], feed_dict={x: batch_x, 
               y: batch_y}) 
     epoch_loss += c 
     i+=batch_size 

      print('Epoch', epoch, 'completed out of', hm_epochs, 'loss:', epoch_loss) 

     # correct = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1)) 
     # accuracy = tf.reduce_mean(tf.cast(correct, 'float')) 
     predicted_class = tf.greater(prediction,0.5) 
     correct = tf.equal(predicted_class, tf.equal(y,1.0)) 
     accuracy = tf.reduce_mean(tf.cast(correct, 'float')) 

     # print (test_x.shape) 
     # accuracy = tf.nn.l2_loss(prediction-y,name="squared_error_test_cost")/test_x.shape[0] 
     print('Accuracy:', accuracy.eval({x: test_x, y: test_y})) 

train_neural_network(x) 

В частности, (перенос обсуждения от предыдущего вопроса) я снял один слой - hidden_3_layer. Измененный

prediction = neural_network_model(x)

в

prediction = tf.sigmoid(neural_network_model(x)) 

и добавил predicted_class, correct, accuracy часть в соответствии с ответом Нила. Я также изменил все -1s на 0s в моем csv.

Это мой след:

('Epoch', 0, 'completed out of', 10, 'loss:', 37.312037646770477) 
('Epoch', 1, 'completed out of', 10, 'loss:', 37.073578298091888) 
('Epoch', 2, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 3, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 4, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 5, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 6, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 7, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 8, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Epoch', 9, 'completed out of', 10, 'loss:', 37.035196363925934) 
('Accuracy:', 0.42608696) 

Как вы можете видеть, потеря не уменьшается. Поэтому я не знаю, работает ли он по-прежнему.

Это результаты нескольких повторных запусков. Результаты качаются дико:

('Epoch', 0, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 1, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 2, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 3, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 4, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 5, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 6, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 7, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 8, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Epoch', 9, 'completed out of', 10, 'loss:', 26.513012945652008) 
('Accuracy:', 0.60124224) 

другой:

('Epoch', 0, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 1, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 2, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 3, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 4, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 5, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 6, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 7, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 8, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 9, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Accuracy:', 1.0) 

и еще:

('Epoch', 0, 'completed out of', 10, 'loss:', 23.163824260234833) 
('Epoch', 1, 'completed out of', 10, 'loss:', 22.88000351190567) 
('Epoch', 2, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 3, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 4, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 5, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 6, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 7, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 8, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Epoch', 9, 'completed out of', 10, 'loss:', 22.873702049255371) 
('Accuracy:', 0.99627328) 

Я также видел точность значения 0,0 -_-

--- ------------ EDIT ---------------

Некоторые сведения о передаче данных и данных. Я использую ежедневные данные о запасах для IBM от Yahoo! финансирование на 20-летний (почти) период. Это составляет примерно 5200 строк записей.

Вот как я его обработки:

import numpy as np 
import pandas as pd 
from sklearn.preprocessing import MinMaxScaler 
import csv 
import pickle 

def create_feature_sets_and_labels(test_size = 0.2): 
    df = pd.read_csv("ibm.csv") 
    df = df.iloc[::-1] 
    features = df.values 
    testing_size = int(test_size*len(features)) 
    train_x = list(features[1:,1:6][:-testing_size]) 
    train_y = list(features[1:,7][:-testing_size]) 
    test_x = list(features[1:,1:6][-testing_size:]) 
    test_y = list(features[1:,7][-testing_size:]) 
    scaler = MinMaxScaler(feature_range=(-5,5)) 
    train_x = scaler.fit_transform(train_x) 
    train_y = scaler.fit_transform(train_y) 
    test_x = scaler.fit_transform(test_x) 
    test_y = scaler.fit_transform(test_y) 

    return train_x, train_y, test_x, test_y 

if __name__ == "__main__": 
    train_x, train_y, test_x, test_y = create_feature_sets_and_labels() 
    with open('stockdata.pickle', 'wb') as f: 
     pickle.dump([train_x, train_y, test_x, test_y], f) 

колонка 0 является дата. Таким образом, это не используется как функция. Также не колонка 7. Я нормализовал данные с использованием sklearnMinMaxScaler() в диапазоне от -5 до 5.

------------- ИЗМЕНИТЬ 2 ------- ------------

Я заметил, что система не меняет свою точность, когда данные представлены в ненормированной форме.

+0

Хорошо, я снова сменил код. Точность все еще колеблется между 65-100. Я также попытался изменить значение своей эпохи, чтобы найти, где потери начинаются до плато, но они продолжают уменьшаться даже на 100 эпох. –

+0

Повороты точности кажутся немного странными. Возможно, я что-то пропустил. Не могли бы вы добавить некоторые сведения о входных данных и о том, как вы их предварительно обрабатываете? Насколько велика установка обучения и набор тестов (поведение, которое вы описываете, я ожидаю от очень небольшого набора данных)? Являются ли эти стандартные данные из общедоступного источника? Есть ли сильный перекос в основном положительные или в основном отрицательные классы? –

+0

Также давайте проверим форму ваших данных истинного класса. Что произойдет, если вы измените 'y = tf.placeholder ('float')' на 'y = tf.placeholder ('float', [None, 1])'? –

ответ

4

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

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

  • Значения X (элементы ввода) в табличной форме, каждая строка является примером, каждый столбец является признаком. Значения должны быть численными и масштабированными для использования с нейронной сетью. Тестирование и сбор данных необходимо масштабировать одинаково - это не означает использование одного и того же .fit_transform, потому что это снова подходит для масштабирования.

  • Значения Y (выходные метки) в табличной форме, каждая строка соответствует примеру одной и той же строки X, каждый столбец является истинным значением вывода. Для задач классификации значения обычно равны 0 и 1, и не должны повторно масштабироваться, поскольку они представляют собой членство в классе.

Это переписана вашей create_feature_sets_and_labels функции делает вещи правильно:

def create_feature_sets_and_labels(test_size = 0.2): 
    df = pd.read_csv("ibm.csv") 
    df = df.iloc[::-1] 
    features = df.values 
    testing_size = int(test_size*len(features)) 

    train_x = np.array(features[1:,1:6][:-testing_size]).astype(np.float32) 
    train_y = np.array(features[1:,7][:-testing_size]).reshape(-1, 1).astype(np.float32) 

    test_x = np.array(features[1:,1:6][-testing_size:]).astype(np.float32) 
    test_y = np.array(features[1:,7][-testing_size:]).reshape(-1, 1).astype(np.float32) 

    scaler = MinMaxScaler(feature_range=(-5,5)) 

    scaler.fit(train_x) 

    train_x = scaler.transform(train_x) 
    test_x = scaler.transform(test_x) 

    return train_x, train_y, test_x, test_y 

Важные отличия от версии:

  • Используя приведение типа np.array, не list (незначительные разницы)

  • y valu es являются табличными [n_examples, n_outputs] (основная разница, ваша форма вектора строки является причиной многих проблем позже)

  • Скальмер подходит после применения к чертам (большая разница, если вы масштабируете поезд и данные теста отдельно, вы ничего не предсказываете смысл)

  • скалер является не применяется к выходам (большая разница для классификатором, вы хотите значение поезда и испытаний, чтобы быть 0,1 для содержательного обучения и точности отчетности)

есть также некоторые проблемы с вашим кодом для обучения этих данных:

  • y = tf.placeholder('float') должны быть y = tf.placeholder('float', [None, 1]). Это не имеет никакого отношения к обработке, но правильно генерирует ошибку, когда y - неправильная форма. Эта ошибка была бы ключом гораздо раньше, что все идет не так.

  • n_nodes_hl1 = 500 и n_nodes_hl2 = 500 могут быть значительно ниже, и сеть будет работать намного лучше, например. n_nodes_hl1 = 10 и n_nodes_hl2 = 10 - это главным образом из-за того, что вы используете большие начальные значения для весов, вы можете альтернативно масштабировать весов, а для более сложных данных вы можете захотеть сделать это вместо этого. В этом случае проще уменьшить количество скрытых нейронов.

  • Как мы уже говорили в комментариях, начало вашей функции train_neural_network должен выглядеть следующим образом:

    output = neural_network_model(x) 
    prediction = tf.sigmoid(output) 
    cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(output, y)) 
    optimizer = tf.train.AdamOptimizer().minimize(cost) 
    

    . , , это большая разница. Используя sigmoid_cross_entropy_with_logits, вы взяли на себя обязательство использовать значение предварительного преобразования выходного уровня для обучения. Но вы все равно хотите, чтобы предсказанные значения измеряли точность (или для любого другого использования сети, где вы хотите прочитать предсказанное значение).

  • Для последовательного измерения потерь, вы хотите иметь средний убыток на примере, так что вам нужно разделить вас сумму в среднем за партию по количеству партий: 'loss:', epoch_loss/(len(train_x)/batch_size)

Если я делаю все эти исправления, и запустите это с еще несколькими эпохами - например 50, то я получаю типичную потерю 0.7 и точность измерения 0.5 - и это происходит достаточно надежно, но немного движется из-за изменений стартовых весов. Точность не очень стабильна и, возможно, страдает от переполнения, которую вы вообще не допускаете (и вы должны прочитать о методах, чтобы помочь измерять и управлять перегрузкой, это важная часть обучения NN надежно)

Значение 0.5 может показаться плохим. Это можно улучшить, изменив сетевую архитектуру или метапараметры. Я могу спуститься до 0.43 тренировочных потерь и до 0.83 точности теста, например, путем замены tf.nn.relu на tf.tanh в скрытых слоях и работает на 500 эпох.

Чтобы узнать больше о нейронных сетях, что измерять при обучении и что может стоить изменить в вашей модели, вы захотите изучить этот предмет более подробно.

+0

Это было отлично! Спасибо огромное! –

+0

Любые указатели на точность стабилизации? Мои значения точности по-прежнему меняются совсем немного. Я пытаюсь запустить свою модель за два месяца данных. Примерно 60 строк. –

+0

@VineetKaushik: Код вашей модели - это очень простая нейронная сеть, и есть много изменений, которые вы могли бы внести, в том числе кросс-валидация, регуляризация, добавление мониторинга и т. Д. Вероятно, проблемы с точностью вызваны перенасыщением, поскольку нет защиты от этого в вашем коде.Я думаю, вам нужно прекратить играть с этой моделью и сделать еще несколько направленных исследований, таких как курс «MOOC» в нейронных сетях, чтобы вы могли узнать об этих вещах. –

Смежные вопросы