Экспортированная модель tflite предсказывает неверные результаты - PullRequest
0 голосов
/ 31 января 2019

У меня есть обученная пользовательская модель Tensorflow, и я хочу использовать ее в своем приложении для iOS через Firebase MLKit.Модель представляет собой простую нейронную сеть 4 на 4 с одним скрытым слоем, подобным этому.

num_data_input = 4
num_units = 12
num_display = 4

xd = tf.placeholder(tf.float32, [None, num_data_input])

w1 = tf.Variable(tf.truncated_normal([num_data_input, num_units],dtype=tf.float32))
b1 = tf.Variable(tf.zeros([num_units],dtype=tf.float32))
hidden1 = tf.nn.sigmoid(tf.matmul(xd, w1) + b1)

w0 = tf.Variable(tf.zeros([num_units, num_display],dtype=tf.float32))
b0 = tf.Variable(tf.zeros([num_display],dtype=tf.float32))
p = tf.nn.softmax(tf.matmul(hidden1, w0) + b0)

ref = tf.placeholder(tf.float32, [None,num_display])
loss = -tf.reduce_sum(ref * tf.log(p))

train_step = tf.train.AdamOptimizer().minimize(loss)
correct_prediction = tf.equal(tf.argmax(p, 1), tf.argmax(ref, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

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

После обучения около 10000 итераций lossснизился до 0,3.(Это не достаточно хорошо, но это не проблема).

Сразу после тренировки я получил такие значения.

print("input", dataarray[0][0])
print("output", sess.run(p, {xd: np.array(dataarray[0][0], dtype=np.float32).reshape(1,4)}))
# Results in:
# input [-87.43277416700528, -81.06589379945419, -71.74611110703701, -71.10851819430701]
# output [[1.5792685e-14 1.7755997e-01 7.4530774e-01 7.7132232e-02]]

print("input", dataarray[10][0])
print("output", sess.run(p, {xd: np.array(dataarray[10][0], dtype=np.float32).reshape(1,4)}))
# Results in:
# input [-86.87348060585144, -79.92684778533435, -71.24158331694396, -71.81342917898614]
# output [[1.30361505e-14 1.73598051e-01 7.51829445e-01 7.45724738e-02]]

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

Получив этот результат, я создал модель tflite с saved_model вкод Python

tf.saved_model.simple_save(sess, "model", inputs={"input": xd}, outputs={"output": p})

и tflite_convert из командной строки

tflite_convert --output_file=tmp/model.tflite --saved_model_dir=model

Затем импортируйте его в мой проект Swift через облако:

    let conditions = ModelDownloadConditions(isWiFiRequired: true, canDownloadInBackground: true)
    let cloudModelSource = CloudModelSource(
        modelName: "my-model",
        enableModelUpdates: false,
        initialConditions: conditions,
        updateConditions: conditions
    )
    let registrationSuccessful = ModelManager.modelManager().register(cloudModelSource)

    let options = ModelOptions(
        cloudModelName: "my-model",
        localModelName: nil)
    interpreter = ModelInterpreter.modelInterpreter(options: options)

    ioOptions = ModelInputOutputOptions()
    do {
        try ioOptions.setInputFormat(index: 0, type: .float32, dimensions: [1, 4])
        try ioOptions.setOutputFormat(index: 0, type: .float32, dimensions: [1, 4])
    } catch let error as NSError {
        print("Failed to set input or output format with error: \(error.localizedDescription)")
    }

и выполните прогноз:

    // 1st value
    let inputValues: [Double] = [-78.07635984967995, -76.68000728404165, -73.98016027165527, -74.77428875130332] 
    // 2nd value
    // let inputValues: [Double] = [-86.87348060585144, -79.92684778533435, -71.24158331694396, -71.81342917898614]

    let inputs = ModelInputs()
    let converted: [Float32] = inputValues.map { Float32($0) }
    do {
        try inputs.addInput([converted])
    } catch let error {
        print("Failed to add input: \(error)")
    }

    interpreter.run(inputs: inputs, options: ioOptions) { (outputs, error) in
        guard error == nil, let outputs = outputs else { return }
        do {
            if let ov = try outputs.output(index: 0) as? [[NSNumber]] {
                print("output = \(ov)") 
                // output = [[0.089901, 0.2951571, 0.2564065, 0.3585353]]
                // ^ Different from above result in python!
                //   And gives me the same value even when the input value is switched to "2nd value" above
            }
        } catch let error {
            print("output retrieval error: \(error)")
        }
    }
}

Во-первых, выходное значение из кода Swift отличается от значения в Python.И вдобавок ко всему, я пробовал с разными значениями, они все дают мне одинаковое значение.Я также пробовал с реальным значением сигнала, но это дало мне то же значение почти во всех случаях.Только когда я даю ему некоторые экстремальные значения далеко за пределами моего ожидаемого диапазона, он показывает разные значения.

Видите ли вы какие-либо проблемы в моем коде Python или Swift-коде?Или что-то отсутствует в моем преобразовании модели tflite?

Любая информация полезна.

Спасибо

1 Ответ

0 голосов
/ 06 февраля 2019

Частично решено.Или, точнее говоря, это была другая проблема.

Предоставляя модель из локального комплекта, она работала как ожидалось.

Я обнаружил, что даже я заменил модель в облаке, приложение продолжало использоватьпредыдущая модель.

Я не упоминал выше, но я пробовал разные модели tflite, прежде чем получить результат выше.И я не обращал особого внимания на его первый результат, так как знал, что модель была довольно неполной.Если бы я обратил на это больше внимания, я бы обнаружил ранее, что результат не изменился вообще.

В любом случае мне теперь нужно выяснить, почему поиск из облака не будет работать, как ожидалось, ноЯ надеюсь, что эта информация поможет кому-то еще.

...