Upgrade Dan Percepat Skill Python Anda Di Tahun 2023 - CRUDPRO

Upgrade Dan Percepat Skill Python Anda Di Tahun 2023

Upgrade Dan Percepat Skill Python Anda Di Tahun 2023

Python adalah bahasa pemrograman yang paling banyak digunakan dalam domain pengetahuan data, dan popularitasnya semakin meningkat. Semua sektor ilmu data sudah berkembang pesat dalam beberapa tahun terakhir.

Pada artikel ini, kami akan menunjukkan kepada Anda tujuh tips mengenai cara meningkatkan keterampilan Python Anda. Seringkali beberapa hal kecil yang membuat perbedaan big. Cara-caranya akan memperkaya hidup Anda sebagai Ilmuwan Data. Itu sebabnya kami memberikan Anda tujuh tipss yang dapat Anda dipraktikkan sekarang. Penasaran?

Sebagai Ilmuwan Data, Anda kerap harus berurusan dengan data dalam jumlah big. Untuk alasan ini, Anda harus membuat code secara efektif dalam hal waktu berjalan dan memori. Code Python Anda juga harus terancang dengan baik dan mudah dibaca. Strategi akan membantu Anda menulis code Python yang efektif dan mudah dibaca.

tips 1: Percepat NumPy

NumPy adalah pustaka Python untuk bekerja secara efisien dengan array. Ini juga menawarkan operasi vektorisasi yang cepat dan optimal. Tetapi! Itu tidak mendukung pemrosesan paralel. Sebagai alternatif NumPy, Anda dapat menggunakan NumExpr.

NumExpr mencapai kinerja yang jauh lebih baik daripada NumPy karena mendukung multi-threading. Selain itu, ini menghindari pengalokasian memori untuk hasil diantaranya.

Pertama, Anda harus menginstal package NumPy dan NumExpr. Sebagai contoh:

$ pip install numpy numexpr

Lihat contoh dan coba.

import numpy as np
import numexpr as ne
import timeit

var1 = np.random.random(2**27)
var2 = np.random.random(2**27)

%timeit np.sin(var1) / np.cos(var2)
# 2.73 s

%timeit ne.evaluate("sin(var1) / cos(var2)")
# 566 ms

Pernyataan itu dilakukan kira-kira 5x lebih cepat dengan NumExpr. Jadi jika Anda ingin mempercepat pernyataan NumPy Anda, ini memberi Anda cara untuk melakukannya.

NumExpr berfungsi paling baik saat Anda memiliki array big. Ini juga mengembangkan kinerja maksimalnya jika Anda memiliki komputer yang kuat dengan banyak inti. Untuk alasan ini, kami merekomendasikan NumExpr saat kedua kondisi ini ada. Untuk operasi array kecil, Anda juga dapat menggunakan NumPy, karena perbedaan kinerjanya sangat minim. Alasannya adalah NumExpr membagi operan array menjadi potongan-potongan kecil. Potongan ini dengan mudah masuk ke dalam cache CPU. Potongan didistribusikan di antara inti CPU yang tersedia, memungkinkan eksekusi paralel.

Jika Anda ingin mempelajari lebih lanjut tentang NumExpr, lihat repositori GitHub NumExpr.

tips 2: Alternatif cepat untuk panda apply()

Fungsi pandas apply() dapat menjalankan fungsi di sepanjang sumbu bingkai data. Banyak pemrogram menggunakan fungsi apply() yang dikombinasikan dengan fungsi lambda. Tapi bagaimana Anda bisa meningkatkan kinerja fungsi apply()?

Anda dapat menggunakan package lebih cepat. package ini menerapkan fungsi dengan sangat cepat ke frame atau chain data. Fungsi pandas apply() berjalan pada satu inti, dan yang lebih cepat menyediakan banyak dukungan inti.

Pertama, Anda perlu menginstal package swifter.

$ pip install swifter

Setelah instalasi Anda dapat mencobanya langsung.

import pandas as pd
import numpy as np
import swifter
import timeit

df = pd.DataFrame({'a': np.random.randint(7, 10, 10**7)})

# pandas apply()
%timeit  df.apply(lambda x: x**7)
# 54 ms

# swifter.apply()
%timeit  df.swifter.apply(lambda x: x**7)
# 37.5 ms

Contoh sederhana ini menunjukkan bahwa fungsi swifter.apply() memiliki waktu proses yang lebih cepat. Perbedaannya terutama terlihat pada komputer yang kuat dengan banyak inti. Jika Anda memerlukan peningkatan kinerja dalam proyek berikutnya, pertimbangkan package yang lebih cepat.

tips 3: Menggunakan Fungsi Python Bawaan

Seringkali Anda mengimplementasikan suatu fungsi dan tidak tahu bahwa itu sudah ada di Python. Apalagi jika Anda berasal dari bahasa pemrograman lain seperti C atau C++. Pertama, Anda harus selalu memeriksa apakah fungsi bawaan Python sudah ada. Fungsi bawaan Python jauh lebih cepat daripada implementasi khusus, jadi Anda harus selalu menggunakannya. Contoh berikut menunjukkan hal ini.

import numpy as np
from time import perf_counter

result_list = []
company_list = ["Tesla", "Block", "Palantir", "Apple"]
company_list_sample = np.repeat(company_list, 10**7)

start = perf_counter()
for company in company_list_sample:
  result_list.append(company.lower())
print(perf_counter()-start)
# 17.13 s

start = perf_counter()
result_list = map(str.lower, company_list_sample)
print(perf_counter()-start)
# 0.97 s

Pada kode di atas, kita mereplikasi daftar empat entri 10 juta kali, sehingga kita mendapatkan daftar 40 juta entri. Kemudian kami mengonversi string dalam daftar menjadi huruf kecil. Anda dapat melihat bahwa fungsi bawaan sekitar 17 kali lebih cepat. Apalagi dengan jumlah data yang besar, tips ini membawa peningkatan performa yang sangat besar. Jadi gunakan fungsi bawaan!

Ada banyak lagi fungsi bawaan, seperti min(), max(), all(), dll. Lakukan riset sendiri jika Anda memerlukan fungsi Python tertentu. Itu sangat berharga.

tips 4: Gunakan pemahaman daftar alih-alih loop

Pemrogram sering menggunakan daftar dalam kombinasi dengan loop untuk menyimpan hasil yang dihitung. Namun, Approach ini tidak efisien dalam hal waktu berjalan. Untuk alasan ini, lebih baik menggunakan pemahaman daftar, yang memiliki kinerja lebih baik. Contoh berikut menunjukkan perbedaan kinerja.

import numpy as np
from time import perf_counter

result_list_loop = []
result_list_com = []

number_round = 10000000

start = perf_counter()
for i in range(number_round):
  result_list_loop.append(i*i)
print(perf_counter()-start)
# 1.47 s

start = perf_counter()
result_list_com = [i*i for i in range(number_round)]
print(perf_counter()-start)
# 0.69 s

print(result_list_com[10])
# 100

Apa yang dapat kita pelajari dari contoh ini? Gunakan pemahaman daftar jika memungkinkan. Pemahaman daftar agak kontroversial dalam pemrograman. Beberapa pemrogram merasa sintaks sulit dibaca, karena satu baris kode mengekspresikan semua pernyataan. Menurut pendapat kami, sintaksnya jelas dan ringkas. Ini masalah selera, tapi kinerjanya lebih baik dengan pemahaman daftar.

Pemahaman daftar dimulai dengan tanda kurung buka [. Lalu ada perhitungan dari for-loop. Kemudian muncul header loop dengan tiga elemen (keyword for, run variable, length of the loop). Pemahaman daftar ditutup dengan tanda kurung tutup ]. Setelah Anda memahami sintaksnya, Anda dapat menulis for-loop jauh lebih padat.

Tapi bagaimana dalam hal penggunaan memori? Bagaimana kita bisa mengurangi ruang memori? Sangat disarankan dengan daftar big jika kita ingin melakukan operasi lebih lanjut pada daftar tersebut. Dalam contoh kami, kami menyimpan 10000000 nilai dalam daftar. Tetapi apakah kita harus menyimpan semua entri secara langsung, atau kita hanya membutuhkannya saat diperlukan?

Dalam kasus ini, kita dapat menggunakan generator. Generator membuat item daftar saat dibutuhkan. Akibatnya, generator membutuhkan lebih sedikit memori dan memiliki waktu pengoperasian yang lebih baik. Lihatlah contoh berikut.

import sys 
from time import perf_counter

print(sys.getsizeof(result_list_com), 'bytes')
# 89095160 bytes

start = perf_counter()
result_gen = (i*i for i in range(number_round))
print(perf_counter()-start)
# 0.22 ms

print(sys.getsizeof(result_gen), 'bytes')
# 112 bytes

print(list(result_gen)[10])
# 100

Kita dapat melakukan semua operasi seperti pada contoh sebelumnya. Satu-satunya perbedaan adalah kita sekarang menggunakan () bukan []. Alih-alih daftar, kami menyimpan generator. Approach ini lebih hemat memori. Periksa apakah Anda dapat menggunakan pemahaman daftar atau generator dalam proyek Anda. Mereka dapat meningkatkan kinerja dan mengurangi memori.

tips 5: Menggabungkan dikte dengan sintaks asterisk ganda **

Bagaimana Anda menggabungkan kamus? Anda dapat melakukannya dengan satu baris. Kami menggunakan sintaks asterisk **. Dalam contoh berikut, Anda dapat melihat cara kerjanya.

dict_1 = {'company': 'Tesla', 'founding': 2002}
dict_2 = {'company': 'Tesla', 'founding': 2003, 'CEO': 'Elon Musk'}

dict_merged = {**dict_1, **dict_2}
print(dict_merged)
# {'company': 'Tesla', 'Founding': 2003, 'CEO': 'Elon Musk'}

Pertama, kami mendefinisikan dua kamus dengan pasangan nilai kunci yang identik dan berbeda. Fondasi Tesla adalah pada tahun 2003, jadi dict_2 lebih mutakhir. Jika kedua kamus berisi kunci yang sama dan nilai yang berbeda, maka nilai kamus terakhir akan digunakan. Setelah penggabungan, kamus baru berisi ketiga pasangan kunci-nilai. Sintaksnya ringkas dan padat, jadi penggabungannya sangat mudah. Dan yang terbaik adalah Anda dapat menggabungkan tiga kamus atau lebih. Trik ini dapat menghemat banyak waktu.

Metode lain adalah metode update. Metode ini memperbarui kamus pertama dan tidak membuat salinan. Lihatlah contoh berikut.

dict_1 = {'company': 'Tesla', 'founding': 2002}
dict_2 = {'company': 'Tesla', 'founding': 2003, 'CEO': 'Elon Musk'}

dict_1.update(dict_2)
print(dict_1)
# {'company': 'Tesla', 'Founding': 2003, 'CEO': 'Elon Musk'}

Kerugian dari metode update adalah Anda hanya dapat menggunakan satu kamus untuk memperbarui. Jika Anda ingin menggabungkan kamus di masa mendatang, ingat tips ini.

tips 6: Jangan mengimpor modul yang tidak diperlukan

Anda mungkin pernah mendengar tips ini berkali-kali, tetapi tips ini dapat meningkatkan performa kode Anda secara signifikan. Tidak perlu mengimpor seluruh perpustakaan. Anda biasanya hanya membutuhkan fungsi-fungsi tertentu saja. Selain itu, kode Anda membutuhkan waktu lama untuk memulai karena seluruh pustaka harus diimpor terlebih dahulu. Seharusnya tidak demikian. Selain itu, Anda kemudian harus mengakses fungsi individual melalui notasi titik. Itu sangat tidak efisien, dan Anda harus menghindari notasi titik. Contoh berikut menunjukkan hal ini.

import math
from time import perf_counter

start = perf_counter()
variable = math.exp(7)
print(perf_counter()-start)
# 8.47-05 s

Dalam contoh ini, kami menggunakan fungsi math.exp() dengan notasi titik. Itu mengarah pada kinerja kode Anda yang buruk. Juga, kami telah mengimpor seluruh perpustakaan matematika, meskipun kami hanya memerlukan fungsi exp().

from math import exp
from time import perf_counter

start = perf_counter()
variable = exp(7)
print(perf_counter()-start)
# 4.51-05 s

Dalam contoh ini, kami mengimpor fungsi exp() tanpa notasi titik. Dengan menggunakan trik ini, kita dapat mengurangi separuh waktu eksekusi kode kita. Itu keren!

tips 7: Gunakan kompiler just-in-time

Numba adalah kompiler just-in-time (jit) yang bekerja dengan baik dengan loop, array, dan fungsi NumPy. Dekorator digunakan untuk menginstruksikan Numba untuk mengkompilasi fungsi tertentu dengan Numba. Numba mengkompilasi fungsi yang didekorasi secara tepat waktu ke dalam kode mesin sehingga semua atau sebagian kode berjalan dengan kecepatan kode mesin asli.

Pertama kita harus menginstal Numba melalui pip.

pip install numba

Setelah instalasi berhasil, Anda dapat menggunakan Numba. Lihatlah contoh berikut:

import numpy as np
from numba import jit
import timeit

var = np.random.random(10**7)
num_loop = 10000

def foo(var):
    result = 0
    for i in range(num_loop):
        result += 1
    result = np.sin(var) + np.cos(var)
    return result               
%timeit foo(var)
# 154 ms

@jit(nopython=True)
def foo_numba(var):
    result = 0
    for i in range(num_loop):
        result += 1
    result = np.sin(var) + np.cos(var)
    return result    

%timeit foo_numba(var)
# 76.3 ms

Anda dapat melihat bahwa dekorator di atas fungsi foo mempercepat kode. Dekorator nopython=True menunjukkan bahwa kompilasi akan berjalan tanpa keterlibatan juru bahasa Python. Numba mempercepat eksekusi loop dan fungsi trigonometri NumPy. Namun, itu tidak dapat digunakan dengan semua fungsi Python. Berikut kelebihan dan kekurangan Numba:

Kontra:

  • Numba tidak mendukung panda.
  • Kode yang tidak didukung dijalankan melalui juru bahasa dan memiliki overhead Numba tambahan.
  • Hanya dukungan tidak resmi pada M1/Arm64.

Kelebihan:

  • Dukungan yang sangat baik untuk array dan fungsi NumPy, dan loop.
  • Dukungan untuk Nvidia CUDA. Itu dapat digunakan dengan baik untuk pengembangan jaringan saraf berdasarkan NumPy.

Kontra dan pro menunjukkan bahwa Numba harus digunakan terutama untuk operasi NumPy. Selain itu, Anda harus selalu memeriksa di awal apakah Numba cocok untuk penerapannya masing-masing.

Kesimpulan

Pada artikel ini kita telah mempelajari cara meningkatkan efisiensi kode Anda dalam hal waktu berjalan dan memori. Pelajaran yang dipelajari:

  • NumPy tidak mendukung pemrosesan paralel. Anda dapat menggunakan NumExpr untuk itu.
  • Fungsi pandas apply() dapat dipercepat dengan lebih cepat.
  • Periksa apakah ada fungsi bawaan.
  • Gunakan pemahaman daftar alih-alih loop. Periksa apakah generator cocok untuk proyek Anda.
  • Menggabungkan dikte dengan sintaks asterisk ganda **.
  • Jangan mengimpor modul yang tidak perlu.
  • Jika Anda mengalami masalah waktu berjalan, Anda dapat menggunakan kompiler just-in-time. Kompiler just-in-time mempercepat kode Anda.

Terima kasih, Semoga Bermanfaat!