Lượng tử hóa sau đào tạo

Lượng tử hóa sau đào tạo là một kỹ thuật chuyển đổi có thể giảm kích thước mô hình đồng thời cải thiện độ trễ của bộ tăng tốc phần cứng và CPU, với độ chính xác của mô hình ít bị suy giảm. Bạn có thể lượng hóa mô hình TensorFlow float đã được đào tạo khi bạn chuyển đổi nó sang định dạng TensorFlow Lite bằng cách sử dụng TensorFlow Lite Converter .

Phương pháp tối ưu hóa

Có một số tùy chọn lượng tử hóa sau đào tạo để lựa chọn. Dưới đây là bảng tóm tắt về các lựa chọn và lợi ích mà chúng cung cấp:

Kĩ thuật Lợi ích Phần cứng
Lượng tử hóa dải động Nhỏ hơn 4 lần, tăng tốc gấp 2 lần gấp 3 lần CPU
Lượng tử hóa số nguyên đầy đủ Nhỏ hơn 4 lần, gấp 3 lần + tăng tốc CPU, Edge TPU, Vi điều khiển
Lượng tử hóa Float16 Nhỏ hơn gấp đôi, tăng tốc GPU CPU, GPU

Cây quyết định sau có thể giúp xác định phương pháp lượng tử hóa sau đào tạo nào là tốt nhất cho trường hợp sử dụng của bạn:

các tùy chọn tối ưu hóa sau đào tạo

Lượng tử hóa dải động

Hình thức lượng tử hóa sau đào tạo đơn giản nhất chỉ lượng tử hóa các trọng số từ dấu phẩy động đến số nguyên, có độ chính xác 8 bit:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

Theo suy luận, trọng số được chuyển đổi từ độ chính xác 8 bit sang dấu phẩy động và được tính bằng cách sử dụng hạt nhân dấu phẩy động. Việc chuyển đổi này được thực hiện một lần và được lưu vào bộ nhớ đệm để giảm độ trễ.

Để cải thiện hơn nữa độ trễ, các toán tử "dải động" tự động lượng tử hóa các kích hoạt dựa trên phạm vi của chúng thành 8-bit và thực hiện các phép tính với trọng số và kích hoạt 8-bit. Tối ưu hóa này cung cấp độ trễ gần với suy luận điểm cố định hoàn toàn. Tuy nhiên, các kết quả đầu ra vẫn được lưu trữ bằng cách sử dụng dấu phẩy động để tốc độ tăng tốc với các hoạt động phạm vi động ít hơn so với tính toán điểm cố định đầy đủ.

Lượng tử hóa số nguyên đầy đủ

Bạn có thể nhận được các cải tiến hơn nữa về độ trễ, giảm mức sử dụng bộ nhớ tối đa và khả năng tương thích với các thiết bị phần cứng hoặc bộ gia tốc chỉ số nguyên bằng cách đảm bảo tất cả mô hình toán học đều được lượng tử hóa số nguyên.

Để lượng tử hóa số nguyên đầy đủ, bạn cần hiệu chỉnh hoặc ước tính phạm vi, tức là (tối thiểu, tối đa) của tất cả các tenxơ dấu phẩy động trong mô hình. Không giống như các tensors không đổi như trọng số và độ lệch, các tensors thay đổi như đầu vào mô hình, kích hoạt (đầu ra của các lớp trung gian) và đầu ra mô hình không thể được hiệu chỉnh trừ khi chúng ta chạy một vài chu kỳ suy luận. Do đó, bộ chuyển đổi yêu cầu một tập dữ liệu đại diện để hiệu chỉnh chúng. Tập dữ liệu này có thể là một tập con nhỏ (khoảng 100-500 mẫu) của dữ liệu đào tạo hoặc xác nhận. Tham khảo hàm representative_dataset() bên dưới.

Từ phiên bản TensorFlow 2.7, bạn có thể chỉ định tập dữ liệu đại diện thông qua chữ ký như ví dụ sau:

def representative_dataset():
  for data in dataset:
    yield {
      "image": data.image,
      "bias": data.bias,
    }

Nếu có nhiều hơn một chữ ký trong mô hình TensorFlow đã cho, bạn có thể chỉ định nhiều tập dữ liệu bằng cách chỉ định các khóa chữ ký:

def representative_dataset():
  # Feed data set for the "encode" signature.
  for data in encode_signature_dataset:
    yield (
      "encode", {
        "image": data.image,
        "bias": data.bias,
      }
    )

  # Feed data set for the "decode" signature.
  for data in decode_signature_dataset:
    yield (
      "decode", {
        "image": data.image,
        "hint": data.hint,
      },
    )

Bạn có thể tạo tập dữ liệu đại diện bằng cách cung cấp danh sách tensor đầu vào:

def representative_dataset():
  for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100):
    yield [tf.dtypes.cast(data, tf.float32)]

Kể từ phiên bản TensorFlow 2.7, chúng tôi khuyên bạn nên sử dụng phương pháp dựa trên chữ ký so với phương pháp dựa trên danh sách tensor đầu vào vì thứ tự tensor đầu vào có thể dễ dàng lật.

Đối với mục đích thử nghiệm, bạn có thể sử dụng một tập dữ liệu giả như sau:

def representative_dataset():
    for _ in range(100):
      data = np.random.rand(1, 244, 244, 3)
      yield [data.astype(np.float32)]
 

Số nguyên với dự phòng float (sử dụng đầu vào / đầu ra float mặc định)

Để lượng tử hóa hoàn toàn số nguyên một mô hình, nhưng sử dụng toán tử float khi chúng không có triển khai số nguyên (để đảm bảo chuyển đổi diễn ra suôn sẻ), hãy sử dụng các bước sau:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()

Chỉ số nguyên

Tạo mô hình chỉ số nguyên là trường hợp sử dụng phổ biến của TensorFlow Lite dành cho Vi điều khiểnTPU Coral Edge .

Ngoài ra, để đảm bảo khả năng tương thích với các thiết bị chỉ số nguyên (chẳng hạn như vi điều khiển 8-bit) và bộ gia tốc (chẳng hạn như Coral Edge TPU), bạn có thể thực thi lượng tử hóa số nguyên đầy đủ cho tất cả các hoạt động bao gồm đầu vào và đầu ra, bằng cách sử dụng các bước sau:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Lượng tử hóa Float16

Bạn có thể giảm kích thước của mô hình dấu phẩy động bằng cách định lượng trọng số thành float16, tiêu chuẩn IEEE cho số dấu phẩy động 16 bit. Để cho phép lượng tử hóa trọng lượng float16, hãy sử dụng các bước sau:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

Ưu điểm của lượng tử hóa float16 như sau:

  • Nó làm giảm kích thước mô hình xuống một nửa (vì tất cả các trọng lượng trở thành một nửa kích thước ban đầu của chúng).
  • Nó gây ra sự mất độ chính xác tối thiểu.
  • Nó hỗ trợ một số đại biểu (ví dụ: đại biểu GPU) có thể hoạt động trực tiếp trên dữ liệu float16, dẫn đến thực thi nhanh hơn so với tính toán float32.

Các nhược điểm của lượng tử hóa float16 như sau:

  • Nó không làm giảm độ trễ nhiều như một phép toán lượng tử hóa điểm cố định.
  • Theo mặc định, một mô hình lượng tử hóa float16 sẽ "dequantize" các giá trị trọng số thành float32 khi chạy trên CPU. (Lưu ý rằng người ủy quyền GPU sẽ không thực hiện việc dequantization này, vì nó có thể hoạt động trên dữ liệu float16.)

Chỉ số nguyên: kích hoạt 16 bit với trọng số 8 bit (thử nghiệm)

Đây là một sơ đồ lượng tử hóa thử nghiệm. Nó tương tự như lược đồ "chỉ số nguyên", nhưng các kích hoạt được lượng tử hóa dựa trên phạm vi của chúng đến 16 bit, trọng số được lượng tử hóa ở dạng số nguyên 8 bit và độ lệch được lượng tử hóa thành số nguyên 64 bit. Điều này được gọi là lượng tử hóa 16x8 hơn nữa.

Ưu điểm chính của lượng tử hóa này là nó có thể cải thiện độ chính xác đáng kể, nhưng chỉ làm tăng một chút kích thước mô hình.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

Nếu lượng tử hóa 16x8 không được hỗ trợ cho một số toán tử trong mô hình, thì mô hình vẫn có thể được lượng tử hóa, nhưng các toán tử không được hỗ trợ được giữ trong float. Tùy chọn sau nên được thêm vào target_spec để cho phép điều này.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

Ví dụ về các trường hợp sử dụng mà các cải tiến về độ chính xác được cung cấp bởi sơ đồ lượng tử hóa này bao gồm: * siêu độ phân giải, * xử lý tín hiệu âm thanh như khử nhiễu và định dạng chùm, * khử nhiễu hình ảnh, * tái tạo HDR từ một hình ảnh duy nhất.

Nhược điểm của lượng tử hóa này là:

  • Hiện tại, suy luận chậm hơn đáng kể so với số nguyên đầy đủ 8-bit do thiếu việc triển khai nhân được tối ưu hóa.
  • Hiện tại nó không tương thích với các đại biểu TFLite tăng tốc phần cứng hiện có.

Có thể tìm thấy hướng dẫn cho chế độ lượng tử hóa này tại đây .

Độ chính xác của mô hình

Vì các trọng số được lượng tử hóa sau đào tạo, nên có thể bị mất độ chính xác, đặc biệt là đối với các mạng nhỏ hơn. Các mô hình lượng tử hóa đầy đủ được đào tạo trước được cung cấp cho các mạng cụ thể trên TensorFlow Hub . Điều quan trọng là phải kiểm tra độ chính xác của mô hình lượng tử hóa để xác minh rằng bất kỳ sự suy giảm nào về độ chính xác đều nằm trong giới hạn chấp nhận được. Có các công cụ để đánh giá độ chính xác của mô hình TensorFlow Lite .

Ngoài ra, nếu độ chính xác giảm quá cao, hãy xem xét sử dụng đào tạo nhận thức lượng tử hóa . Tuy nhiên, làm như vậy đòi hỏi các sửa đổi trong quá trình đào tạo mô hình để thêm các nút lượng tử hóa giả mạo, trong khi các kỹ thuật lượng tử hóa sau đào tạo trên trang này sử dụng một mô hình đã được đào tạo trước.

Biểu diễn cho tenxơ lượng tử hóa

Lượng tử hóa 8 bit tính gần đúng giá trị dấu phẩy động bằng công thức sau.

\[real\_value = (int8\_value - zero\_point) \times scale\]

Biểu diễn có hai phần chính:

  • Trọng số trên mỗi trục (hay còn gọi là mỗi kênh) hoặc trọng số trên tensor được biểu thị bằng các giá trị phần bù của int8 hai trong phạm vi [-127, 127] với zero-point bằng 0.

  • Kích hoạt / đầu vào trên mỗi tensor được biểu thị bằng giá trị bổ sung của int8 hai trong phạm vi [-128, 127], với một điểm 0 trong phạm vi [-128, 127].

Để có cái nhìn chi tiết về sơ đồ lượng tử hóa của chúng tôi, vui lòng xem thông số kỹ thuật lượng tử hóa của chúng tôi. Các nhà cung cấp phần cứng muốn cắm vào giao diện đại biểu của TensorFlow Lite được khuyến khích triển khai sơ đồ lượng tử hóa được mô tả ở đó.