Ngày Cộng đồng ML là ngày 9 tháng 11! Tham gia với chúng tôi để cập nhật từ TensorFlow, JAX, và nhiều hơn nữa Tìm hiểu thêm

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ể quantize một mô hình TensorFlow phao đã được đào tạo khi bạn chuyển đổi nó sang định dạng TensorFlow Lite sử dụng TensorFlow Lite Chuyển đổi .

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 4x, 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 đô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 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, 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 những 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 máy 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. Hãy tham khảo những representative_dataset() chức năng dưới đây.

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

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

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ý thay vì 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 số nguyên duy nhất mô hình là một trường hợp sử dụng chung cho TensorFlow Lite cho vi điều khiểnCoral Cạnh TPUs .

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 dành 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()

Các ư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 đến 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 các 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.

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ó.

Một hướng dẫn cho chế độ lượng tử này có thể được tìm thấy ở đâ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. Pre-đào tạo mô hình lượng tử hóa hoàn toàn được cung cấp cho các mạng cụ thể trong kho mô hình TensorFlow Lite . Đ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ó những công cụ để đánh giá TensorFlow Lite mô hình chính xác .

Ngoài ra, nếu thả chính xác là quá cao, xem xét sử dụng lượng tử hóa đào tạo nhận thức được . 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ả 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ô 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 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 (hay còn gọi là trên 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 two 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].

Đối với một cái nhìn chi tiết về chương trình lượng tử hóa của chúng tôi, vui lòng xem của chúng tôi đặc tả lượng tử . 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ả ở đó.