Tôi có nên sử dụng @ tf.feft cho tất cả các chức năng không?


8

Một hướng dẫn chính thức về @tf.functionnói:

Để có được hiệu suất cao nhất và để mô hình của bạn có thể triển khai ở bất cứ đâu, hãy sử dụng tf.feft để tạo biểu đồ ra khỏi chương trình của bạn. Nhờ AutoGraph, một lượng mã Python đáng ngạc nhiên chỉ hoạt động với tf.feft, nhưng vẫn còn những cạm bẫy cần cảnh giác.

Các khuyến nghị và khuyến nghị chính là:

  • Đừng dựa vào các tác dụng phụ của Python như đột biến đối tượng hoặc nối thêm danh sách.
  • tf.function hoạt động tốt nhất với ops TensorFlow, thay vì opP NumPy hoặc Python nguyên thủy.
  • Khi nghi ngờ, sử dụng for x trong thành ngữ y.

Nó chỉ đề cập đến cách thực hiện các @tf.functionchức năng chú thích chứ không phải khi nào sử dụng nó.

Có một heuristic về cách quyết định liệu tôi ít nhất nên cố gắng chú thích một chức năng với tf.function? Dường như không có lý do gì để không làm điều đó, trừ khi tôi lười biếng loại bỏ các tác dụng phụ hoặc thay đổi một số thứ như range()-> tf.range(). Nhưng nếu tôi sẵn sàng làm điều này ...

Có bất kỳ lý do không sử dụng @tf.functioncho tất cả các chức năng?


1
Tại sao thêm các thẻ này? Chúng tôi cũng có thể thêm tensorflow0.1, tensorflow0.2, tensorflow0.3, tensorflow0.4, tensorflow0.5và như vậy, cũng như một thẻ cho mỗi người trong số các tfmodule và các lớp học sau đó. Ngoài ra, tại sao không thêm một thẻ cho mỗi mô-đun chuẩn của Python và các hàm và lớp của nó?
ForceBru

Đó là lý do tại sao tôi đã giới thiệu thẻ tenorflow2.x, bởi vì có những câu hỏi không chỉ liên quan đến hàng chục hoặc dòng chảy mà là thẻ tenorflow2.x. Tuy nhiên, sẽ không phù hợp và không khả thi khi thêm thẻ cho mỗi và mọi phiên bản của thư viện. Lấy ví dụ về Python. Bạn không có python3.4.6 ..... python.3.8.2, nhưng python3.x
Timbus Calin

Một mặt, tf.functionhướng dẫn có nội dung "Trang trí các hàm cấp mô-đun và phương thức của các lớp cấp mô-đun và tránh trang trí các hàm hoặc phương thức cục bộ". Tôi dường như nhớ từ ngữ rõ ràng hơn, như "không trang trí mọi chức năng, sử dụng tf.functiontrong các chức năng cấp cao hơn, như vòng lặp đào tạo", nhưng tôi có thể đánh giá sai (hoặc có thể nó đã bị xóa). OTOH, cuộc thảo luận này có đầu vào thú vị từ các nhà phát triển, cuối cùng có vẻ ổn khi sử dụng nó trong bất kỳ chức năng nào cho tenor / vars.
jdehesa

@jdehesa Các @tf.functionhàm chú thích AFAIK cũng biên dịch các hàm mà chúng tự gọi là biểu đồ. Vì vậy, bạn sẽ chỉ cần chú thích điểm vào mô-đun phù hợp với những gì bạn mô tả. Nhưng nó cũng không ảnh hưởng đến việc chú thích thủ công các chức năng thấp hơn trong ngăn xếp cuộc gọi.
vấn đề

@pro Hiệuofficer Có, vì vậy, trong vấn đề GitHub mà tôi đã liên kết, có một số cuộc thảo luận về việc liệu việc tạo nhiều hàm trung gian có thể có tác động hiệu suất nhẹ hay không, nhưng có vẻ như trình tối ưu hóa đồ thị (grappler) có thể "nội tuyến" nếu cần, nhưng mặt khác tay nếu một cái khác không tf.functionđược gọi nhiều lần thì nó không thể ngăn chặn "sao chép mã" trong biểu đồ, đó là lý do tại sao việc sử dụng rộng rãi dường như được khuyến khích.
jdehesa

Câu trả lời:


4

TLDR: Nó phụ thuộc vào chức năng của bạn và liệu bạn đang trong quá trình sản xuất hay phát triển. Không sử dụng tf.functionnếu bạn muốn có thể gỡ lỗi chức năng của mình một cách dễ dàng hoặc nếu nó nằm trong giới hạn của khả năng tương thích mã AutoGraph hoặc tf.v1. Tôi đặc biệt khuyên bạn nên xem các cuộc thảo luận Inside TensorFlow về AutoGraphChức năng, chứ không phải Phiên .

Sau đây tôi sẽ chia nhỏ các lý do, tất cả được lấy từ thông tin có sẵn trực tuyến của Google.

Nói chung, trình tf.functiontrang trí làm cho một hàm được biên dịch thành một hàm có thể gọi được, thực thi một biểu đồ TensorFlow. Điều này đòi hỏi:

  • Chuyển đổi mã thông qua AutoGraph nếu được yêu cầu (bao gồm mọi chức năng được gọi từ chức năng chú thích)
  • Truy tìm và thực thi mã đồ thị đã tạo

Có thông tin chi tiết có sẵn về các ý tưởng thiết kế đằng sau này.

Lợi ích của việc trang trí một chức năng với tf.function

Lợi ích chung

  • Thực thi nhanh hơn , đặc biệt nếu hàm bao gồm nhiều op nhỏ (Nguồn)

Đối với các chức năng với mã Python / Sử dụng AutoGraph thông qua tf.functiontrang trí

Nếu bạn muốn sử dụng AutoGraph, việc sử dụng tf.functionđược khuyến khích cao hơn là gọi trực tiếp AutoGraph. Lý do cho điều này bao gồm: Phụ thuộc điều khiển tự động, nó được yêu cầu cho một số API, bộ nhớ đệm nhiều hơn và trình trợ giúp ngoại lệ (Nguồn) .

Hạn chế của việc trang trí một chức năng với tf.function

Hạn chế chung

  • Nếu chức năng chỉ bao gồm một vài op đắt tiền, sẽ không có nhiều tăng tốc (Nguồn)

Đối với các chức năng với mã Python / Sử dụng AutoGraph thông qua tf.functiontrang trí

  • Không bắt ngoại lệ (nên được thực hiện ở chế độ háo hức; bên ngoài chức năng được trang trí) (Nguồn)
  • Gỡ lỗi khó hơn nhiều
  • Hạn chế do tác dụng phụ ẩn và luồng kiểm soát TF

Thông tin chi tiết về các hạn chế của AutoGraph có sẵn.

Đối với các hàm có mã tf.v1

  • Không được phép tạo các biến nhiều lần tf.function, nhưng điều này có thể thay đổi khi mã tf.v1 bị loại bỏ (Nguồn)

Đối với các hàm có mã tf.v2

  • Không có nhược điểm cụ thể

Ví dụ về những hạn chế

Tạo các biến nhiều lần

Không được phép tạo các biến nhiều lần, chẳng hạn như vtrong ví dụ sau:

@tf.function
def f(x):
    v = tf.Variable(1)
    return tf.add(x, v)

f(tf.constant(2))

# => ValueError: tf.function-decorated function tried to create variables on non-first call.

Trong đoạn mã sau, điều này được giảm nhẹ bằng cách đảm bảo rằng self.vnó chỉ được tạo một lần:

class C(object):
    def __init__(self):
        self.v = None
    @tf.function
    def f(self, x):
        if self.v is None:
            self.v = tf.Variable(1)
        return tf.add(x, self.v)

c = C()
print(c.f(tf.constant(2)))

# => tf.Tensor(3, shape=(), dtype=int32)

Tác dụng phụ ẩn không được chụp bởi AutoGraph

self.aKhông thể ẩn các thay đổi như trong ví dụ này, dẫn đến lỗi do phân tích chức năng chéo chưa được thực hiện (chưa) (Nguồn) :

class C(object):
    def change_state(self):
        self.a += 1

    @tf.function
    def f(self):
        self.a = tf.constant(0)
        if tf.constant(True):
            self.change_state() # Mutation of self.a is hidden
        tf.print(self.a)

x = C()
x.f()

# => InaccessibleTensorError: The tensor 'Tensor("add:0", shape=(), dtype=int32)' cannot be accessed here: it is defined in another function or code block. Use return values, explicit Python locals or TensorFlow collections to access it. Defined in: FuncGraph(name=cond_true_5, id=5477800528); accessed from: FuncGraph(name=f, id=5476093776).

Thay đổi trong tầm nhìn rõ ràng là không có vấn đề:

class C(object):
    @tf.function
    def f(self):
        self.a = tf.constant(0)
        if tf.constant(True):
            self.a += 1 # Mutation of self.a is in plain sight
        tf.print(self.a)

x = C()
x.f()

# => 1

Ví dụ về giới hạn do dòng điều khiển TF

Điều này nếu câu lệnh dẫn đến lỗi vì giá trị khác cần được xác định cho luồng điều khiển TF:

@tf.function
def f(a, b):
    if tf.greater(a, b):
        return tf.constant(1)

# If a <= b would return None
x = f(tf.constant(3), tf.constant(2))   

# => ValueError: A value must also be returned from the else branch. If a value is returned from one branch of a conditional a value must be returned from all branches.

1
Đây là một bản tóm tắt tốt. Cũng đáng lưu ý rằng khi được gọi từ chế độ háo hức, tf.feft có tổng phí khoảng 200 chúng tôi (cho hoặc nhận) sau cuộc gọi đầu tiên. Gọi một tf.feft từ một tf.feft khác là tốt. Vì vậy, bạn muốn bọc càng nhiều tính toán càng tốt. Nếu không có giới hạn, bạn nên gói toàn bộ chương trình.
Dan Moldovan

Câu trả lời này là tl; dr IMHO và nó không thực sự trả lời câu hỏi của tôi mà chỉ đưa ra thông tin phân mảnh giống như tôi tự tìm thấy. Ngoài ra, nói rằng tôi không nên sử dụng @tf.functioncho sản xuất mà chỉ để phát triển không phải là một giải pháp khả thi. Thứ nhất, trong học máy (ít nhất là trong nghiên cứu), đào tạo trong giai đoạn phát triển cũng tạo ra sản phẩm cuối cùng (mô hình được đào tạo). Thứ hai, trang trí là một thay đổi đáng kể. Tôi không thể đặt chúng vào "sau khi phát triển" và chắc chắn rằng mã này hoạt động giống nhau. Điều này có nghĩa là tôi phải phát triển và thử nghiệm với họ đã có.
vấn đề

@pro Hiệuofficer Xin lỗi vì sự nhầm lẫn. Khi nói về sản xuất trong câu trả lời của tôi, tôi đã xem việc đào tạo (trên tập dữ liệu lớn) là một phần trong đó. Trong nghiên cứu của riêng tôi, tôi phát triển / gỡ lỗi các chức năng của mình với một bộ dữ liệu đồ chơi ở chế độ háo hức, sau đó thêm tf.functionnếu thích hợp.
prouast

2

tf.feft rất hữu ích trong việc tạo và sử dụng các biểu đồ tính toán, chúng nên được sử dụng trong đào tạo và triển khai, tuy nhiên nó không cần thiết cho hầu hết các chức năng của bạn.

Hãy nói rằng chúng tôi đang xây dựng một lớp đặc biệt sẽ tách ra khỏi một mô hình lớn hơn. Chúng tôi không muốn có trình trang trí tf.feft bên trên hàm xây dựng lớp đó bởi vì nó chỉ là một định nghĩa về lớp sẽ trông như thế nào.

Mặt khác, giả sử rằng chúng ta sẽ đưa ra dự đoán hoặc tiếp tục đào tạo bằng cách sử dụng một số chức năng. Chúng tôi muốn có tf.factor trang trí bởi vì chúng tôi thực sự đang sử dụng biểu đồ tính toán để có được một số giá trị.

Một ví dụ tuyệt vời sẽ là xây dựng mô hình bộ mã hóa-giải mã. KHÔNG đặt trình trang trí xung quanh chức năng tạo bộ mã hóa hoặc bộ giải mã hoặc bất kỳ lớp nào, đó chỉ là một định nghĩa về những gì nó sẽ làm. NÊN đặt công cụ trang trí xung quanh phương pháp "tàu" hoặc "dự đoán" bởi vì những người thực sự sẽ sử dụng biểu đồ tính toán để tính toán.


1
Nhưng những gì về tác dụng phụ hoặc ví dụ tf.range(). AFAIK chúng không thể được chuyển đổi tự động. Vì vậy, tôi sẽ cần viết các lớp tùy chỉnh của mình với biểu đồ tự động ngay từ đầu. Vì vậy, tôi không thể chỉ trang trí chức năng gọi (dự đoán).
vấn đề
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.