У меня есть модель, обученная керам и сохраненная как файл.h5. Модель обучается значениям с плавающей запятой с одиночной точностью с использованием бэкэнда tensorflow. Теперь я хочу реализовать аппаратный ускоритель, который выполняет операцию свертки на FPGA Xilinx. Однако, прежде чем я решит использовать ширину битов фиксированной точки, которые будут использоваться на FPGA, мне нужно оценить точность модели, квантовав весовые коэффициенты до 8 или 16 бит. Я наткнулся на квантование тензорного потока, но я не уверен, как я могу собирать веса из каждого слоя, квантовать его и хранить в списке массивов numpy. После того, как все слои квантованы, я хочу установить вес модели для новых сформированных квантованных весов. Может ли кто-нибудь помочь мне сделать это?
Это то, что я пытался сделать до сих пор, чтобы уменьшить точность от float32 до float16. Пожалуйста, дайте мне знать, если это правильный подход.
for i in range(len(w_orginal)):
temp_shape = w_orginal[i].shape
print('Shape of index: '+ str(i)+ 'array is :')
print(temp_shape)
temp_array = w_orginal[i]
temp_array_flat = w_orginal[i].flatten()
for j in range(len(temp_array)):
temp_array_flat[j] = temp_array_flat[j].astype(np.float16)
temp_array_flat = temp_array_flat.reshape(temp_shape)
w_fp_16_test.append(temp_array_flat)
Извините за то, что я не знаком с тензорным потоком, поэтому я не могу дать вам код, но, может быть, мой опыт с квантованием модели caffe может иметь смысл.
Если вы правильно поняли, у вас есть модель tensorflow (float32), которую вы хотите квантовать на int8 и сохранить в numpy.array
.
Во-первых, вы должны прочитать все веса для каждого слоя, который может быть списком python или numpy.array
или что-то еще, это не имеет значения.
Тогда алгоритм квантования будет существенно влиять на точность, вы должны выбрать лучший для своей модели. Однако эти алгоритмы имеют одинаковую шкалу. Все, что вам нужно сделать, - это масштабирование всех весов до -127 до 127 (int8), как и scale
слой без bias
, и запись масштабного коэффициента.
В случае, если вы хотите реализовать его на FPGA, данные также должны быть qiantized. Здесь у нас есть новая проблема - результат int8 * int8 - это int16, что является очевидным переполнением.
Чтобы решить эту проблему, мы создаем новый параметр - shift - для возврата результата int16 к int8. Обратите внимание, что параметр shift
не будет постоянным 8, предположим, что 0 * 0 = 0, нам вообще не нужно сдвигать результат.
Последний вопрос, который мы думаем, заключается в том, что если сеть слишком глубока, результат слоя может переполняться из-за некоторых необоснованных параметров scale
, поэтому мы не можем напрямую квантовать каждый отдельный слой, не думая о других слоях.
После того, как вся фишка закончилась на FPGA, если вы хотите выполнить dequantize int8 to float32, просто используйте последний параметр масштаба (конечного результата), чтобы сделать несколько mul/div (в зависимости от того, как вы определяете scale
).
Это базовый алгоритм квантования, другие, такие как tf.quantization
могут иметь более высокую точность. Теперь у нас есть квантованная модель, вы можете сохранить ее во все, что вам нравится, это не тяжелая работа.
PS Почему много? файл bin лучше всего подходит для FPGA, не так ли?
И есть ли у вас представление о внедрении softmax на FPGA? Я смущен этим...