CẬP NHẬT - 1/15/2020 : cách thực hành tốt nhất hiện tại đối với kích thước lô nhỏ phải là cung cấp trực tiếp đầu vào cho mô hình - tức là preds = model(x)
và nếu các lớp hoạt động khác nhau khi đào tạo / suy luận , model(x, training=False)
. Theo cam kết mới nhất, điều này hiện được ghi nhận .
Tôi chưa điểm chuẩn những điều này, nhưng theo thảo luận về Git , nó cũng đáng để thử predict_on_batch()
- đặc biệt là với các cải tiến trong TF 2.1.
CULPRIT TUYỆT VỜI : self._experimental_run_tf_function = True
. Đó là thử nghiệm . Nhưng nó không thực sự xấu.
Để bất kỳ nhà phát triển TensorFlow đọc: làm sạch mã của bạn . Đó là một mớ hỗn độn. Và nó vi phạm các thực hành mã hóa quan trọng, chẳng hạn như một chức năng làm một việc ; _process_inputs
thực hiện nhiều hơn "quy trình đầu vào", tương tự cho _standardize_user_data
. "Tôi không trả đủ" - nhưng bạn làm lương, trong hiệp phụ thời gian dành cho sự hiểu biết cụ của riêng bạn, và trong người dùng điền trang Các vấn đề của bạn với lỗi dễ dàng hơn giải quyết với một mã số rõ ràng hơn.
TÓM TẮT : nó chỉ chậm hơn một chút với compile()
.
compile()
thiết lập một cờ nội bộ gán một chức năng dự đoán khác nhau predict
. Hàm này xây dựng một biểu đồ mới theo mỗi cuộc gọi, làm chậm nó xuống so với không biên dịch. Tuy nhiên, sự khác biệt chỉ được phát âm khi thời gian đào tạo ngắn hơn nhiều so với thời gian xử lý dữ liệu . Nếu chúng ta tăng kích thước mô hình lên ít nhất là cỡ trung bình, hai cái sẽ trở nên bằng nhau. Xem mã ở phía dưới.
Sự tăng nhẹ thời gian xử lý dữ liệu này được bù đắp nhiều hơn bởi khả năng đồ thị được khuếch đại. Vì sẽ hiệu quả hơn khi chỉ giữ một biểu đồ mô hình xung quanh, một biểu đồ biên dịch trước bị loại bỏ. Tuy nhiên : nếu mô hình của bạn nhỏ so với dữ liệu, bạn tốt hơn là không cần compile()
suy luận mô hình. Xem câu trả lời khác của tôi cho một cách giải quyết.
TÔI NÊN LÀM GÌ?
So sánh hiệu suất mô hình được biên dịch so với không biên dịch như tôi có trong mã ở phía dưới.
- Biên dịch nhanh hơn : chạy
predict
trên một mô hình biên dịch.
- Biên dịch chậm hơn : chạy
predict
trên một mô hình chưa biên dịch.
Có, cả hai đều có thể, và nó sẽ phụ thuộc vào (1) kích thước dữ liệu; (2) kích thước mô hình; (3) phần cứng. Mã ở phía dưới thực sự cho thấy mô hình được biên dịch nhanh hơn, nhưng 10 lần lặp là một mẫu nhỏ. Xem "cách giải quyết" trong câu trả lời khác của tôi để biết "cách thực hiện".
CHI TIẾT :
Điều này mất một lúc để gỡ lỗi, nhưng rất vui. Dưới đây tôi mô tả các thủ phạm chính mà tôi đã phát hiện ra, trích dẫn một số tài liệu có liên quan và hiển thị kết quả hồ sơ dẫn đến nút cổ chai cuối cùng.
( FLAG == self.experimental_run_tf_function
, cho ngắn gọn)
Model
theo mặc định khởi tạo với FLAG=False
. compile()
đặt nó thành True
.
predict()
liên quan đến việc có được chức năng dự đoán, func = self._select_training_loop(x)
- Không có bất kỳ kwarg đặc biệt nào được chuyển đến
predict
và compile
, tất cả các cờ khác đều như vậy:
- (A)
FLAG==True
->func = training_v2.Loop()
- (B)
FLAG==False
->func = training_arrays.ArrayLikeTrainingLoop()
- Từ chuỗi mã nguồn , (A) phụ thuộc nhiều vào biểu đồ, sử dụng chiến lược phân phối nhiều hơn và các op có xu hướng tạo và phá hủy các phần tử biểu đồ, điều này có thể ảnh hưởng đến hiệu suất.
Thủ phạm thực sự : _process_inputs()
, chiếm 81% thời gian chạy . Thành phần chính của nó? _create_graph_function()
, 72% thời gian chạy . Phương pháp này thậm chí không tồn tại cho (B) . Tuy nhiên, sử dụng một mô hình cỡ trung bình, _process_inputs
bao gồm ít hơn 1% thời gian chạy . Mã ở dưới cùng, và kết quả hồ sơ theo sau.
QUY TRÌNH DỮ LIỆU :
(A) : <class 'tensorflow.python.keras.engine.data_adapter.TensorLikeDataAdapter'>
, được sử dụng trong _process_inputs()
. Mã nguồn có liên quan
(B) : numpy.ndarray
, được trả lại bởi convert_eager_tensors_to_numpy
. Mã nguồn có liên quan , và ở đây
CHỨC NĂNG THỰC HIỆN MÔ HÌNH (ví dụ dự đoán)
(A) : chức năng phân phối , và ở đây
(B) : hàm phân phối (khác nhau) và tại đây
HỒ SƠ : kết quả cho mã trong câu trả lời khác của tôi, "mô hình nhỏ" và trong câu trả lời này, "mô hình trung bình":
Mô hình nhỏ : 1000 lần lặp,compile()
Mô hình nhỏ : 1000 lần lặp, không compile()
Mô hình trung bình : 10 lần lặp
TÀI LIỆU (gián tiếp) về tác dụng của compile()
: nguồn
Không giống như các hoạt động khác của TensorFlow, chúng tôi không chuyển đổi đầu vào số python thành tenxơ. Hơn nữa, một biểu đồ mới được tạo cho mỗi giá trị số python riêng biệt , ví dụ như gọi g(2)
và g(3)
sẽ tạo ra hai biểu đồ mới
function
khởi tạo một biểu đồ riêng cho mỗi bộ hình dạng và kiểu dữ liệu đầu vào duy nhất . Ví dụ: đoạn mã sau sẽ dẫn đến ba biểu đồ riêng biệt được theo dõi, vì mỗi đầu vào có hình dạng khác nhau
Một đối tượng tf.feft có thể cần ánh xạ tới nhiều biểu đồ tính toán dưới mui xe. Điều này chỉ được hiển thị khi hiệu suất (biểu đồ theo dõi có chi phí tính toán và bộ nhớ khác không ) nhưng không ảnh hưởng đến tính chính xác của chương trình
QUỐC GIA :
from tensorflow.keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from tensorflow.keras.layers import Flatten, Dropout
from tensorflow.keras.models import Model
import numpy as np
from time import time
def timeit(func, arg, iterations):
t0 = time()
for _ in range(iterations):
func(arg)
print("%.4f sec" % (time() - t0))
batch_size = 32
batch_shape = (batch_size, 400, 16)
ipt = Input(batch_shape=batch_shape)
x = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
x = LSTM(512, activation='relu', return_sequences=True)(ipt)
x = Conv1D(128, 400, 1, padding='same')(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(128, activation='relu')(x)
x = Dense(64, activation='relu')(x)
out = Dense(1, activation='sigmoid')(x)
model = Model(ipt, out)
X = np.random.randn(*batch_shape)
timeit(model.predict, X, 10)
model.compile('adam', loss='binary_crossentropy')
timeit(model.predict, X, 10)
Đầu ra :
34.8542 sec
34.7435 sec