У меня есть обученная пользовательская модель 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?
Любая информация полезна.
Спасибо