Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

API NumPy di ​​TensorFlow

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Gambaran

TensorFlow mengimplementasikan subset NumPy API , tersedia sebagai tf.experimental.numpy . Hal ini memungkinkan menjalankan kode NumPy, yang dipercepat oleh TensorFlow, sekaligus mengizinkan akses ke semua API TensorFlow.

Mempersiapkan

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow.experimental.numpy as tnp
import timeit

print("Using TensorFlow version %s" % tf.__version__)
Using TensorFlow version 2.4.0

Array TensorFlow NumPy ND

Sebuah contoh dari tf.experimental.numpy.ndarray , disebut ND Array, merupakan array padat multidimensi diberikan dtype ditempatkan pada perangkat tertentu. Masing-masing dari objek ini secara internal membungkus tf.Tensor . Lihat kelas array ND untuk metode yang berguna seperti ndarray.T , ndarray.reshape , ndarray.ravel , dan lainnya.

Pertama buat objek array ND, lalu panggil metode yang berbeda.

# Create an ND array and check out different attributes.
ones = tnp.ones([5, 3], dtype=tnp.float32)
print("Created ND array with shape = %s, rank = %s, "
      "dtype = %s on device = %s\n" % (
          ones.shape, ones.ndim, ones.dtype, ones.data.device))

# Check out the internally wrapped `tf.Tensor` object.
print("The ND array wraps a tf.Tensor: %s\n" % ones.data)

# Try commonly used member functions.
print("ndarray.T has shape %s" % str(ones.T.shape))
print("narray.reshape(-1) has shape %s" % ones.reshape(-1).shape)
Created ND array with shape = (5, 3), rank = 2, dtype = float32 on device = /job:localhost/replica:0/task:0/device:GPU:0

The ND array wraps a tf.Tensor: tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]], shape=(5, 3), dtype=float32)

ndarray.T has shape (3, 5)
narray.reshape(-1) has shape 15

Jenis promosi

TensorFlow NumPy API memiliki semantik yang terdefinisi dengan baik untuk mengonversi literal menjadi array ND, serta untuk melakukan promosi jenis pada input array ND. Silakan lihat np.result_type untuk lebih jelasnya. Saat mengonversi literal ke array ND, NumPy lebih memilih tipe lebar seperti tnp.int64 dan tnp.float64 .

Sebaliknya, tf.convert_to_tensor lebih suka tf.int32 dan tf.float32 jenis untuk mengkonversi konstanta untuk tf.Tensor . API TensorFlow membiarkan input tf.Tensor tidak berubah dan tidak melakukan promosi jenis padanya.

Pada contoh berikutnya, Anda akan melakukan promosi tipe. Pertama, jalankan penambahan pada input larik ND dari berbagai jenis dan catat jenis keluarannya. Tidak satu pun dari jenis promosi ini akan diizinkan pada objek tf.Tensor lurus. Terakhir, konversikan literal ke array ND menggunakan ndarray.asarray dan catat jenis yang dihasilkan.

print("Type promotion for operations")
values = [tnp.asarray(1, dtype=d) for d in
          (tnp.int32, tnp.int64, tnp.float32, tnp.float64)]
for i, v1 in enumerate(values):
  for v2 in values[i + 1:]:
    print("%s + %s => %s" % (v1.dtype, v2.dtype, (v1 + v2).dtype))

print("Type inference during array creation")
print("tnp.asarray(1).dtype == tnp.%s" % tnp.asarray(1).dtype)
print("tnp.asarray(1.).dtype == tnp.%s\n" % tnp.asarray(1.).dtype)
Type promotion for operations
int32 + int64 => int64
int32 + float32 => float64
int32 + float64 => float64
int64 + float32 => float64
int64 + float64 => float64
float32 + float64 => float64
Type inference during array creation
tnp.asarray(1).dtype == tnp.int64
tnp.asarray(1.).dtype == tnp.float64


Penyiaran

Mirip dengan TensorFlow, NumPy mendefinisikan semantik kaya untuk nilai "penyiaran". Anda dapat melihat panduan penyiaran NumPy untuk informasi lebih lanjut dan membandingkannya dengan semantik penyiaran TensorFlow .

x = tnp.ones([2, 3])
y = tnp.ones([3])
z = tnp.ones([1, 2, 1])
print("Broadcasting shapes %s, %s and %s gives shape %s" % (
    x.shape, y.shape, z.shape, (x + y + z).shape))
Broadcasting shapes (2, 3), (3,) and (1, 2, 1) gives shape (1, 2, 3)

Pengindeksan

NumPy mendefinisikan aturan pengindeksan yang sangat canggih. Lihat panduan Pengindeksan NumPy . Perhatikan penggunaan array ND sebagai indeks di bawah ini.

x = tnp.arange(24).reshape(2, 3, 4)

print("Basic indexing")
print(x[1, tnp.newaxis, 1:3, ...], "\n")

print("Boolean indexing")
print(x[:, (True, False, True)], "\n")

print("Advanced indexing")
print(x[1, (0, 0, 1), tnp.asarray([0, 1, 1])])
Basic indexing
ndarray<tf.Tensor(
[[[16 17 18 19]
  [20 21 22 23]]], shape=(1, 2, 4), dtype=int64)> 

Boolean indexing
ndarray<tf.Tensor(
[[[ 0  1  2  3]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [20 21 22 23]]], shape=(2, 2, 4), dtype=int64)> 

Advanced indexing
ndarray<tf.Tensor([12 13 17], shape=(3,), dtype=int64)>

# Mutation is currently not supported
try:
  tnp.arange(6)[1] = -1
except TypeError:
  print("Currently, TensorFlow NumPy does not support mutation.")
Currently, TensorFlow NumPy does not support mutation.

Contoh Model

Selanjutnya, Anda dapat melihat cara membuat model dan menjalankan inferensi di atasnya. Model sederhana ini menerapkan lapisan relu diikuti dengan proyeksi linier. Bagian selanjutnya akan menunjukkan cara menghitung gradien untuk model ini menggunakan GradientTape TensorFlow.

class Model(object):
  """Model with a dense and a linear layer."""

  def __init__(self):
    self.weights = None

  def predict(self, inputs):
    if self.weights is None:
      size = inputs.shape[1]
      # Note that type `tnp.float32` is used for performance.
      stddev = tnp.sqrt(size).astype(tnp.float32)
      w1 = tnp.random.randn(size, 64).astype(tnp.float32) / stddev
      bias = tnp.random.randn(64).astype(tnp.float32)
      w2 = tnp.random.randn(64, 2).astype(tnp.float32) / 8
      self.weights = (w1, bias, w2)
    else:
      w1, bias, w2 = self.weights
    y = tnp.matmul(inputs, w1) + bias
    y = tnp.maximum(y, 0)  # Relu
    return tnp.matmul(y, w2)  # Linear projection

model = Model()
# Create input data and compute predictions.
print(model.predict(tnp.ones([2, 32], dtype=tnp.float32)))
ndarray<tf.Tensor(
[[-0.89206064 -0.18108469]
 [-0.89206064 -0.18108469]], shape=(2, 2), dtype=float32)>

TensorFlow NumPy dan NumPy

TensorFlow NumPy mengimplementasikan subset dari spesifikasi NumPy lengkap. Sementara lebih banyak simbol akan ditambahkan seiring waktu, ada fitur sistematis yang tidak akan didukung dalam waktu dekat. Ini termasuk dukungan NumPy C API, integrasi Swig, urutan penyimpanan Fortran, tampilan dan stride_tricks , dan beberapa dtype s (seperti np.recarray dan np.object ). Untuk detail selengkapnya, lihat Dokumentasi API NumPy TensorFlow .

Interoperabilitas NumPy

Array TensorFlow ND dapat beroperasi dengan fungsi NumPy. Objek ini mengimplementasikan antarmuka __array__ . NumPy menggunakan antarmuka ini untuk mengubah argumen fungsi menjadi nilai np.ndarray sebelum memprosesnya.

Demikian pula, fungsi TensorFlow NumPy dapat menerima input dari berbagai jenis termasuk tf.Tensor dan np.ndarray . Input ini diubah ke array ND dengan memanggil ndarray.asarray padanya.

Konversi array ND ke dan dari np.ndarray dapat memicu penyalinan data aktual. Silakan lihat bagian salinan buffer untuk lebih jelasnya.

# ND array passed into NumPy function.
np_sum = np.sum(tnp.ones([2, 3]))
print("sum = %s. Class: %s" % (float(np_sum), np_sum.__class__))

# `np.ndarray` passed into TensorFlow NumPy function.
tnp_sum = tnp.sum(np.ones([2, 3]))
print("sum = %s. Class: %s" % (float(tnp_sum), tnp_sum.__class__))
sum = 6.0. Class: <class 'numpy.float64'>
sum = 6.0. Class: <class 'tensorflow.python.ops.numpy_ops.np_arrays.ndarray'>

# It is easy to plot ND arrays, given the __array__ interface.
labels = 15 + 2 * tnp.random.randn(1000)
_ = plt.hist(labels)

png

Salinan penyangga

Memadukan TensorFlow NumPy dengan kode NumPy dapat memicu penyalinan data. Ini karena TensorFlow NumPy memiliki persyaratan yang lebih ketat pada penyelarasan memori dibandingkan dengan NumPy.

Saat np.ndarray diteruskan ke TensorFlow NumPy, ini akan memeriksa persyaratan penyelarasan dan memicu salinan jika diperlukan. Saat meneruskan buffer CPU array ND ke NumPy, biasanya buffer tersebut akan memenuhi persyaratan penyelarasan dan NumPy tidak perlu membuat salinan.

Array ND dapat merujuk ke buffer yang ditempatkan pada perangkat selain memori CPU lokal. Dalam kasus seperti itu, menjalankan fungsi NumPy akan memicu salinan di seluruh jaringan atau perangkat sesuai kebutuhan.

Mengingat hal ini, pencampuran dengan panggilan NumPy API umumnya harus dilakukan dengan hati-hati dan pengguna harus berhati-hati terhadap overhead penyalinan data. Menyisipkan panggilan TensorFlow NumPy dengan panggilan TensorFlow umumnya aman dan menghindari penyalinan data. Lihat bagian tentang interoperabilitas TensorFlow untuk mengetahui detail selengkapnya.

Prioritas operator

TensorFlow NumPy mendefinisikan __array_priority__ lebih tinggi dari NumPy. Artinya, untuk operator yang melibatkan array ND dan np.ndarray , yang pertama akan diutamakan, yaitu masukan np.ndarray akan diubah menjadi array ND dan implementasi TensorFlow NumPy pada operator akan dipanggil.

x = tnp.ones([2]) + np.ones([2])
print("x = %s\nclass = %s" % (x, x.__class__))
x = ndarray<tf.Tensor([2. 2.], shape=(2,), dtype=float64)>
class = <class 'tensorflow.python.ops.numpy_ops.np_arrays.ndarray'>

TF NumPy dan TensorFlow

TensorFlow NumPy dibuat di atas TensorFlow dan karenanya beroperasi secara mulus dengan TensorFlow.

tf.Tensor dan array ND

Array ND adalah pembungkus tipis pada tf.Tensor . Jenis ini dapat dikonversi dengan murah satu sama lain tanpa memicu salinan data yang sebenarnya.

x = tf.constant([1, 2])

# Convert `tf.Tensor` to `ndarray`.
tnp_x = tnp.asarray(x)
print(tnp_x)

# Convert `ndarray` to `tf.Tensor` can be done in following ways.
print(tnp_x.data)
print(tf.convert_to_tensor(tnp_x))

# Note that tf.Tensor.numpy() will continue to return `np.ndarray`.
print(x.numpy(), x.numpy().__class__)
ndarray<tf.Tensor([1 2], shape=(2,), dtype=int32)>
tf.Tensor([1 2], shape=(2,), dtype=int32)
tf.Tensor([1 2], shape=(2,), dtype=int32)
[1 2] <class 'numpy.ndarray'>

Interoperabilitas TensorFlow

Array ND bisa diteruskan ke TensorFlow API. Panggilan ini secara internal mengonversi input array ND ke tf.Tensor . Seperti yang disebutkan sebelumnya, konversi semacam itu tidak benar-benar melakukan salinan data, bahkan untuk data yang ditempatkan pada akselerator atau perangkat jarak jauh.

Sebaliknya, objek tf.Tensor dapat diteruskan ke API tf.experimental.numpy . Input ini secara internal akan diubah ke array ND tanpa melakukan salinan data.

# ND array passed into TensorFlow function.
# This returns a `tf.Tensor`.
tf_sum = tf.reduce_sum(tnp.ones([2, 3], tnp.float32))
print("Output = %s" % tf_sum)

# `tf.Tensor` passed into TensorFlow NumPy function.
# This returns an ND array.
tnp_sum = tnp.sum(tf.ones([2, 3]))
print("Output = %s" % tnp_sum)
Output = tf.Tensor(6.0, shape=(), dtype=float32)
Output = ndarray<tf.Tensor(6.0, shape=(), dtype=float32)>

Prioritas operator

Jika array ND dan objek tf.Tensor digabungkan menggunakan operator, aturan prioritas digunakan untuk menentukan objek mana yang mengeksekusi operator. Ini dikontrol oleh nilai __array_priority__ ditentukan oleh kelas-kelas ini.

tf.Tensor mendefinisikan __array_priority__ lebih tinggi dari array ND. Artinya, input array ND akan diubah menjadi tf.Tensor dan versi operator tf.Tensor akan dipanggil.

Kode di bawah ini menunjukkan bagaimana hal itu mempengaruhi tipe keluaran.

x = tnp.ones([2, 2]) + tf.ones([2, 1])
print("x = %s\nClass = %s" % (x, x.__class__))
x = tf.Tensor(
[[2. 2.]
 [2. 2.]], shape=(2, 2), dtype=float32)
Class = <class 'tensorflow.python.framework.ops.EagerTensor'>

Gradien dan Jacobian: tf. GradientTape

GradientTape TensorFlow dapat digunakan untuk propagasi mundur melalui kode TensorFlow dan TensorFlow NumPy. GradientTape API juga dapat mengembalikan keluaran array ND.

Gunakan model yang dibuat di bagian Model Contoh , dan hitung gradien dan jacobian.

def create_batch(batch_size=32):
  """Creates a batch of input and labels."""
  return (tnp.random.randn(batch_size, 32).astype(tnp.float32),
          tnp.random.randn(batch_size, 2).astype(tnp.float32))

def compute_gradients(model, inputs, labels):
  """Computes gradients of squared loss between model prediction and labels."""
  with tf.GradientTape() as tape:
    assert model.weights is not None
    # Note that `model.weights` need to be explicitly watched since they
    # are not tf.Variables.
    tape.watch(model.weights)
    # Compute prediction and loss
    prediction = model.predict(inputs)
    loss = tnp.sum(tnp.square(prediction - labels))
  # This call computes the gradient through the computation above.
  return tape.gradient(loss, model.weights)

inputs, labels = create_batch()
gradients = compute_gradients(model, inputs, labels)

# Inspect the shapes of returned gradients to verify they match the
# parameter shapes.
print("Parameter shapes:", [w.shape for w in model.weights])
print("Gradient shapes:", [g.shape for g in gradients])
# Verify that gradients are of type ND array.
assert isinstance(gradients[0], tnp.ndarray)
Parameter shapes: [(32, 64), (64,), (64, 2)]
Gradient shapes: [(32, 64), (64,), (64, 2)]

# Computes a batch of jacobians. Each row is the jacobian of an element in the
# batch of outputs w.r.t. the corresponding input batch element.
def prediction_batch_jacobian(inputs):
  with tf.GradientTape() as tape:
    tape.watch(inputs)
    prediction = model.predict(inputs)
  return prediction, tape.batch_jacobian(prediction, inputs)

inp_batch = tnp.ones([16, 32], tnp.float32)
output, batch_jacobian = prediction_batch_jacobian(inp_batch)
# Note how the batch jacobian shape relates to the input and output shapes.
print("Output shape: %s, input shape: %s" % (output.shape, inp_batch.shape))
print("Batch jacobian shape:", batch_jacobian.shape)
Output shape: (16, 2), input shape: (16, 32)
Batch jacobian shape: (16, 2, 32)

Kompilasi jejak: tf.function

TensorFlow's tf.function bekerja dengan "melacak kompilasi" kode dan kemudian mengoptimalkan jejak ini untuk performa yang jauh lebih cepat. Lihat Pengantar Grafik dan Fungsi .

tf.function juga dapat digunakan untuk mengoptimalkan kode TensorFlow NumPy. Berikut adalah contoh sederhana untuk mendemonstrasikan speedups. Perhatikan bahwa tf.function kode tf.function menyertakan panggilan ke TensorFlow NumPy API, dan input serta outputnya adalah array ND.

inputs, labels = create_batch(512)
print("Eager performance")
compute_gradients(model, inputs, labels)
print(timeit.timeit(lambda: compute_gradients(model, inputs, labels),
                    number=10) * 100, "ms")

print("\ntf.function compiled performance")
compiled_compute_gradients = tf.function(compute_gradients)
compiled_compute_gradients(model, inputs, labels)  # warmup
print(timeit.timeit(lambda: compiled_compute_gradients(model, inputs, labels),
                    number=10) * 100, "ms")
Eager performance
1.3229853999973784 ms

tf.function compiled performance
0.4066010000087772 ms

Vektorisasi: tf.vectorized_map

TensorFlow memiliki dukungan bawaan untuk melakukan vektorisasi loop paralel, yang memungkinkan percepatan satu hingga dua kali lipat. Speedup ini dapat diakses melalui tf.vectorized_map API dan juga berlaku untuk kode TensorFlow NumPy.

Terkadang berguna untuk menghitung gradien dari setiap keluaran dalam sebuah batch dengan elemen batch masukan yang sesuai. Perhitungan seperti itu dapat dilakukan secara efisien menggunakan tf.vectorized_map seperti yang ditunjukkan di bawah ini.

@tf.function
def vectorized_per_example_gradients(inputs, labels):
  def single_example_gradient(arg):
    inp, label = arg
    return compute_gradients(model,
                             tnp.expand_dims(inp, 0),
                             tnp.expand_dims(label, 0))
  # Note that a call to `tf.vectorized_map` semantically maps
  # `single_example_gradient` over each row of `inputs` and `labels`.
  # The interface is similar to `tf.map_fn`.
  # The underlying machinery vectorizes away this map loop which gives
  # nice speedups.
  return tf.vectorized_map(single_example_gradient, (inputs, labels))

batch_size = 128
inputs, labels = create_batch(batch_size)

per_example_gradients = vectorized_per_example_gradients(inputs, labels)
for w, p in zip(model.weights, per_example_gradients):
  print("Weight shape: %s, batch size: %s, per example gradient shape: %s " % (
      w.shape, batch_size, p.shape))
Weight shape: (32, 64), batch size: 128, per example gradient shape: (128, 32, 64) 
Weight shape: (64,), batch size: 128, per example gradient shape: (128, 64) 
Weight shape: (64, 2), batch size: 128, per example gradient shape: (128, 64, 2) 

# Benchmark the vectorized computation above and compare with
# unvectorized sequential computation using `tf.map_fn`.
@tf.function
def unvectorized_per_example_gradients(inputs, labels):
  def single_example_gradient(arg):
    inp, label = arg
    return compute_gradients(model,
                             tnp.expand_dims(inp, 0),
                             tnp.expand_dims(label, 0))

  return tf.map_fn(single_example_gradient, (inputs, labels),
                   fn_output_signature=(tf.float32, tf.float32, tf.float32))

print("Running vectorized computation")
print(timeit.timeit(lambda: vectorized_per_example_gradients(inputs, labels),
                    number=10) * 100, "ms")

print("\nRunning unvectorized computation")
per_example_gradients = unvectorized_per_example_gradients(inputs, labels)
print(timeit.timeit(lambda: unvectorized_per_example_gradients(inputs, labels),
                    number=10) * 100, "ms")
Running vectorized computation
0.3884524000000056 ms

Running unvectorized computation
38.94797479999852 ms

Penempatan perangkat

TensorFlow NumPy dapat melakukan operasi pada CPU, GPU, TPU, dan perangkat jarak jauh. Ini menggunakan mekanisme TensorFlow standar untuk penempatan perangkat. Di bawah ini contoh sederhana menunjukkan bagaimana membuat daftar semua perangkat dan kemudian menempatkan beberapa perhitungan pada perangkat tertentu.

TensorFlow juga memiliki API untuk mereplikasi komputasi di seluruh perangkat dan melakukan pengurangan kolektif yang tidak akan dibahas di sini.

Daftar perangkat

tf.config.list_logical_devices dan tf.config.list_physical_devices dapat digunakan untuk menemukan perangkat apa yang akan digunakan.

print("All logical devices:", tf.config.list_logical_devices())
print("All physical devices:", tf.config.list_physical_devices())

# Try to get the GPU device. If unavailable, fallback to CPU.
try:
  device = tf.config.list_logical_devices(device_type="GPU")[0]
except IndexError:
  device = "/device:CPU:0"
All logical devices: [LogicalDevice(name='/device:CPU:0', device_type='CPU'), LogicalDevice(name='/device:GPU:0', device_type='GPU')]
All physical devices: [PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'), PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

Menempatkan operasi: tf.device

Operasi dapat ditempatkan pada perangkat dengan memanggilnya dalam lingkup tf.device .

print("Using device: %s" % str(device))
# Run operations in the `tf.device` scope.
# If a GPU is available, these operations execute on the GPU and outputs are
# placed on the GPU memory.
with tf.device(device):
  prediction = model.predict(create_batch(5)[0])

print("prediction is placed on %s" % prediction.data.device)
Using device: LogicalDevice(name='/device:GPU:0', device_type='GPU')
prediction is placed on /job:localhost/replica:0/task:0/device:GPU:0

Menyalin array ND di seluruh perangkat: tnp.copy

Panggilan ke tnp.copy , ditempatkan di lingkup perangkat tertentu, akan menyalin data ke perangkat itu, kecuali data sudah ada di perangkat itu.

with tf.device("/device:CPU:0"):
  prediction_cpu = tnp.copy(prediction)
print(prediction.data.device)
print(prediction_cpu.data.device)
/job:localhost/replica:0/task:0/device:GPU:0
/job:localhost/replica:0/task:0/device:CPU:0

Perbandingan kinerja

TensorFlow NumPy menggunakan kernel TensorFlow yang sangat dioptimalkan yang dapat dikirim pada CPU, GPU, dan TPU. TensorFlow juga melakukan banyak pengoptimalan compiler, seperti fusi operasi, yang menghasilkan peningkatan performa dan memori. Lihat pengoptimalan grafik TensorFlow dengan Grappler untuk mempelajari lebih lanjut.

Namun TensorFlow memiliki overhead yang lebih tinggi untuk operasi pengiriman dibandingkan dengan NumPy. Untuk beban kerja yang terdiri dari operasi kecil (kurang dari sekitar 10 mikrodetik), overhead ini dapat mendominasi waktu proses dan NumPy dapat memberikan kinerja yang lebih baik. Untuk kasus lain, TensorFlow biasanya memberikan performa yang lebih baik.

Jalankan tolok ukur di bawah untuk membandingkan performa NumPy dan TensorFlow NumPy untuk berbagai ukuran input.

def benchmark(f, inputs, number=30, force_gpu_sync=False):
  """Utility to benchmark `f` on each value in `inputs`."""
  times = []
  for inp in inputs:
    def _g():
      if force_gpu_sync:
        one = tnp.asarray(1)
      f(inp)
      if force_gpu_sync:
        with tf.device("CPU:0"):
          tnp.copy(one)  # Force a sync for GPU case

    _g()  # warmup
    t = timeit.timeit(_g, number=number)
    times.append(t * 1000. / number)
  return times


def plot(np_times, tnp_times, compiled_tnp_times, has_gpu, tnp_times_gpu):
  """Plot the different runtimes."""
  plt.xlabel("size")
  plt.ylabel("time (ms)")
  plt.title("Sigmoid benchmark: TF NumPy vs NumPy")
  plt.plot(sizes, np_times, label="NumPy")
  plt.plot(sizes, tnp_times, label="TF NumPy (CPU)")
  plt.plot(sizes, compiled_tnp_times, label="Compiled TF NumPy (CPU)")
  if has_gpu:
    plt.plot(sizes, tnp_times_gpu, label="TF NumPy (GPU)")
  plt.legend()
# Define a simple implementation of `sigmoid`, and benchmark it using
# NumPy and TensorFlow NumPy for different input sizes.

def np_sigmoid(y):
  return 1. / (1. + np.exp(-y))

def tnp_sigmoid(y):
  return 1. / (1. + tnp.exp(-y))

@tf.function
def compiled_tnp_sigmoid(y):
  return tnp_sigmoid(y)

sizes = (2 ** 0, 2 ** 5, 2 ** 10, 2 ** 15, 2 ** 20)
np_inputs = [np.random.randn(size).astype(np.float32) for size in sizes]
np_times = benchmark(np_sigmoid, np_inputs)

with tf.device("/device:CPU:0"):
  tnp_inputs = [tnp.random.randn(size).astype(np.float32) for size in sizes]
  tnp_times = benchmark(tnp_sigmoid, tnp_inputs)
  compiled_tnp_times = benchmark(compiled_tnp_sigmoid, tnp_inputs)

has_gpu = len(tf.config.list_logical_devices("GPU"))
if has_gpu:
  with tf.device("/device:GPU:0"):
    tnp_inputs = [tnp.random.randn(size).astype(np.float32) for size in sizes]
    tnp_times_gpu = benchmark(compiled_tnp_sigmoid, tnp_inputs, 100, True)
else:
  tnp_times_gpu = None
plot(np_times, tnp_times, compiled_tnp_times, has_gpu, tnp_times_gpu)

png

Bacaan lebih lanjut