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 ít sự suy giảm về độ chính xác của mô hình. Bạn có thể định lượng một 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 Bộ chuyển đổi TensorFlow Lite .

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 các lựa chọn và lợi ích mà chúng mang lại:

Kỹ thuật Những lợi ích Phần cứng
Lượng tử hóa phạm vi động Nhỏ hơn gấp 4 lần, tăng tốc gấp 2-3 lần CPU
Lượng tử hóa toàn bộ số nguyên Nhỏ hơn gấp 4 lần, tăng tốc gấp 3 lần CPU, Edge TPU, Vi điều khiển
lượng tử hóa float16 Nhỏ hơn gấp 2 lần, tăng tốc GPU CPU, GPU

Cây quyết định sau đây 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:

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

Lượng tử hóa phạm vi động

Lượng tử hóa phạm vi động là điểm bắt đầu được khuyến nghị vì nó giúp giảm mức sử dụng bộ nhớ và tính toán nhanh hơn mà bạn không cần phải cung cấp tập dữ liệu đại diện để hiệu chuẩn. Loại lượng tử hóa này, chỉ lượng tử hóa tĩnh các trọng số từ dấu phẩy động sang số nguyên tại thời điểm chuyển đổi, cung cấp độ 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()

Để tiếp tục giảm độ trễ trong quá trình suy luận, các toán tử "phạm vi động" tự động lượng 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 tính toán với các kích hoạt và trọng số 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 nên tốc độ gia tăng của hoạt động phạm vi động thấp hơn so với tính toán điểm cố định đầy đủ.

Lượng tử hóa toàn bộ số nguyên

Bạn có thể nhận được các cải tiến về độ trễ hơn nữa, 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 máy gia tốc chỉ có số nguyên bằng cách đảm bảo tất cả toán học mô hình đề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, nghĩa 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 tenxơ không đổi như trọng số và độ lệch, các tenxơ 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 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 hợp con nhỏ (khoảng ~100-500 mẫu) của dữ liệu đào tạo hoặc xác thực. Tham khảo hàm đại 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 nhất định, 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 cách tiếp cận dựa trên chữ ký thay vì cách tiếp cận 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 ngược.

Đối với mục đích thử nghiệm, bạn có thể sử dụng 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 có dự phòng float (sử dụng đầu vào/đầu ra float mặc định)

Để lượng tử hóa toàn bộ số nguyên một mô hình, nhưng sử dụng toán tử float khi chúng không triển khai số nguyên (để đảm bảo quá trình 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 các mô hình chỉ số nguyên là trường hợp sử dụng phổ biến cho TensorFlow Lite dành cho Bộ 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ỉ có số nguyên (chẳng hạn như bộ vi điều khiển 8 bit) và máy gia tốc (chẳng hạn như TPU Coral Edge), bạn có thể thực thi lượng tử hóa toàn bộ số nguyên 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 lượng tử hóa các trọng số thành float16, tiêu chuẩn IEEE cho các số dấu phẩy động 16 bit. Để kích hoạt lượng tử hóa trọng số float16, hãy làm theo 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ó giảm kích thước mô hình tới 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 tổn thất tối thiểu về độ chính xác.
  • 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.

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ư lượng tử hóa thành toán học điểm cố định.
  • Theo mặc định, một mô hình lượng tử float16 sẽ "hạ cấp" các giá trị trọng số thành float32 khi chạy trên CPU. (Lưu ý rằng đại biểu GPU sẽ không thực hiện quá trình khử lượng tử 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 kích hoạt được lượng tử hóa dựa trên phạm vi của chúng thành 16 bit, trọng số được lượng tử hóa theo 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 quá trình lượng tử hóa này là nó có thể cải thiện độ chính xác một cách đáng kể, nhưng chỉ làm tăng nhẹ 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ợ vẫn ở dạng thả nổi. Tùy chọn sau sẽ đượ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 cải thiện độ chính xác được cung cấp bởi sơ đồ lượng tử hóa này bao gồm:

  • giải pháp tối ưu,
  • xử lý tín hiệu âm thanh như khử tiếng ồn và tạo chùm tia,
  • 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 việc lượng tử hóa này là:

  • Suy luận hiện tại chậm hơn đáng kể so với số nguyên đầy đủ 8 bit do thiếu triển khai hạt 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 được 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 quá trình đào tạo, nên có thể xảy ra tình trạng mất độ chính xác, đặc biệt đố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 biết lượng tử hóa . Tuy nhiên, làm như vậy yêu cầu 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ả, 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ô hình được đào tạo trước hiện có.

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

Lượng tử hóa 8 bit xấp xỉ các 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 (còn gọi là trên mỗi kênh) hoặc trên mỗi tensor được biểu thị bằng các giá trị bù của int8 two trong phạm vi [-127, 127] với điểm 0 bằng 0.

  • Kích hoạt/đầu vào trên mỗi tenxơ được biểu thị bằng các giá trị bù của int8 two trong phạm vi [-128, 127], với đ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ố lượng tử hóa của chúng tôi. Các nhà cung cấp phần cứng muốn kết nối với giao diện đại biểu của TensorFlow Lite được khuyến khích triển khai lược đồ lượng tử hóa được mô tả ở đó.