Interoperabilitas Python

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub

Swift For TensorFlow mendukung interoperabilitas Python.

Anda dapat mengimpor modul Python dari Swift, memanggil fungsi Python, dan mengonversi nilai antara Swift dan Python.

import PythonKit
print(Python.version)
3.6.9 (default, Oct  8 2020, 12:12:24) 
[GCC 8.4.0]

Mengatur versi Python

Secara default, saat Anda import Python , Swift mencari jalur perpustakaan sistem untuk versi terbaru Python yang diinstal. Untuk menggunakan instalasi Python tertentu, atur variabel lingkungan PYTHON_LIBRARY ke perpustakaan bersama libpython yang disediakan oleh instalasi. Misalnya:

export PYTHON_LIBRARY="~/anaconda3/lib/libpython3.7m.so"

Nama file persisnya akan berbeda di seluruh lingkungan dan platform Python.

Alternatifnya, Anda dapat mengatur variabel lingkungan PYTHON_VERSION , yang memerintahkan Swift untuk mencari jalur perpustakaan sistem untuk versi Python yang cocok. Perhatikan bahwa PYTHON_LIBRARY lebih diutamakan daripada PYTHON_VERSION .

Dalam kode, Anda juga dapat memanggil fungsi PythonLibrary.useVersion , yang setara dengan pengaturan PYTHON_VERSION .

// PythonLibrary.useVersion(2)
// PythonLibrary.useVersion(3, 7)

Catatan: Anda harus menjalankan PythonLibrary.useVersion tepat setelah import Python , sebelum memanggil kode Python apa pun. Itu tidak dapat digunakan untuk mengganti versi Python secara dinamis.

Setel PYTHON_LOADER_LOGGING=1 untuk melihat keluaran debug untuk pemuatan pustaka Python .

Dasar-dasar

Di Swift, PythonObject mewakili objek dari Python. Semua API Python menggunakan dan mengembalikan instance PythonObject .

Tipe dasar di Swift (seperti angka dan array) dapat dikonversi ke PythonObject . Dalam beberapa kasus (untuk literal dan fungsi yang menggunakan argumen PythonConvertible ), konversi terjadi secara implisit. Untuk secara eksplisit memberikan nilai Swift ke PythonObject , gunakan penginisialisasi PythonObject .

PythonObject mendefinisikan banyak operasi standar, termasuk operasi numerik, pengindeksan, dan iterasi.

// Convert standard Swift types to Python.
let pythonInt: PythonObject = 1
let pythonFloat: PythonObject = 3.0
let pythonString: PythonObject = "Hello Python!"
let pythonRange: PythonObject = PythonObject(5..<10)
let pythonArray: PythonObject = [1, 2, 3, 4]
let pythonDict: PythonObject = ["foo": [0], "bar": [1, 2, 3]]

// Perform standard operations on Python objects.
print(pythonInt + pythonFloat)
print(pythonString[0..<6])
print(pythonRange)
print(pythonArray[2])
print(pythonDict["bar"])
4.0
Hello 
slice(5, 10, None)
3
[1, 2, 3]

// Convert Python objects back to Swift.
let int = Int(pythonInt)!
let float = Float(pythonFloat)!
let string = String(pythonString)!
let range = Range<Int>(pythonRange)!
let array: [Int] = Array(pythonArray)!
let dict: [String: [Int]] = Dictionary(pythonDict)!

// Perform standard operations.
// Outputs are the same as Python!
print(Float(int) + float)
print(string.prefix(6))
print(range)
print(array[2])
print(dict["bar"]!)
4.0
Hello 
5..<10
3
[1, 2, 3]

PythonObject mendefinisikan kesesuaian dengan banyak protokol Swift standar:

  • Equatable
  • Comparable
  • Hashable
  • SignedNumeric
  • Strideable
  • MutableCollection
  • Semua protokol ExpressibleBy_Literal

Perhatikan bahwa kesesuaian ini tidak aman untuk tipe: crash akan terjadi jika Anda mencoba menggunakan fungsionalitas protokol dari instance PythonObject yang tidak kompatibel.

let one: PythonObject = 1
print(one == one)
print(one < one)
print(one + one)

let array: PythonObject = [1, 2, 3]
for (i, x) in array.enumerated() {
  print(i, x)
}
True
False
2
0 1
1 2
2 3

Untuk mengonversi tupel dari Python ke Swift, Anda harus mengetahui aritas tupel secara statis.

Panggil salah satu metode instan berikut:

  • PythonObject.tuple2
  • PythonObject.tuple3
  • PythonObject.tuple4
let pythonTuple = Python.tuple([1, 2, 3])
print(pythonTuple, Python.len(pythonTuple))

// Convert to Swift.
let tuple = pythonTuple.tuple3
print(tuple)
(1, 2, 3) 3
(1, 2, 3)

bawaan Python

Akses bawaan Python melalui antarmuka Python global.

// `Python.builtins` is a dictionary of all Python builtins.
_ = Python.builtins

// Try some Python builtins.
print(Python.type(1))
print(Python.len([1, 2, 3]))
print(Python.sum([1, 2, 3]))
<class 'int'>
3
6

Mengimpor modul Python

Gunakan Python.import untuk mengimpor modul Python. Ini berfungsi seperti kata kunci import dengan Python .

let np = Python.import("numpy")
print(np)
let zeros = np.ones([2, 3])
print(zeros)
<module 'numpy' from '/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/numpy/__init__.py'>
[[1. 1. 1.]
 [1. 1. 1.]]

Gunakan fungsi pelemparan Python.attemptImport untuk melakukan impor yang aman.

let maybeModule = try? Python.attemptImport("nonexistent_module")
print(maybeModule)
nil

Konversi dengan numpy.ndarray

Tipe Swift berikut dapat dikonversi ke dan dari numpy.ndarray :

  • Array<Element>
  • ShapedArray<Scalar>
  • Tensor<Scalar>

Konversi berhasil hanya jika dtype numpy.ndarray kompatibel dengan tipe parameter generik Element atau Scalar .

Untuk Array , konversi dari numpy hanya berhasil jika numpy.ndarray adalah 1-D.

import TensorFlow

let numpyArray = np.ones([4], dtype: np.float32)
print("Swift type:", type(of: numpyArray))
print("Python type:", Python.type(numpyArray))
print(numpyArray.shape)
Swift type: PythonObject
Python type: <class 'numpy.ndarray'>
(4,)

// Examples of converting `numpy.ndarray` to Swift types.
let array: [Float] = Array(numpy: numpyArray)!
let shapedArray = ShapedArray<Float>(numpy: numpyArray)!
let tensor = Tensor<Float>(numpy: numpyArray)!

// Examples of converting Swift types to `numpy.ndarray`.
print(array.makeNumpyArray())
print(shapedArray.makeNumpyArray())
print(tensor.makeNumpyArray())

// Examples with different dtypes.
let doubleArray: [Double] = Array(numpy: np.ones([3], dtype: np.float))!
let intTensor = Tensor<Int32>(numpy: np.ones([2, 3], dtype: np.int32))!
[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]

Menampilkan gambar

Anda dapat menampilkan gambar sebaris menggunakan matplotlib , seperti di buku catatan Python.

// This cell is here to display plots inside a Jupyter Notebook.
// Do not copy it into another environment.
%include "EnableIPythonDisplay.swift"
print(IPythonDisplay.shell.enable_matplotlib("inline"))
('inline', 'module://ipykernel.pylab.backend_inline')

let np = Python.import("numpy")
let plt = Python.import("matplotlib.pyplot")

let time = np.arange(0, 10, 0.01)
let amplitude = np.exp(-0.1 * time)
let position = amplitude * np.sin(3 * time)

plt.figure(figsize: [15, 10])

plt.plot(time, position)
plt.plot(time, amplitude)
plt.plot(time, -amplitude)

plt.xlabel("Time (s)")
plt.ylabel("Position (m)")
plt.title("Oscillations")

plt.show()

png

Use `print()` to show values.