บทความตอนที่ 8 เป็นตอนสุดท้ายของชุดไลบรารี ulab ที่เป็นไลบรารีคำนวณทางคณิตศาสตร์ที่สามารถนำมาใช้กับ AI ได้ โดยในบทความตอนนี้กล่าวถึงโมดูลย่อย poly, fft และ filter ซึ่งได้อธิบายการทำงานของแต่ละฟังก์ชันพร้อมยกตัวอย่างการใช้งานเพื่อเป็นแนวทางในการประยุกต์ใช้ต่อไป

poly

โมดูลย่อย poly เป็นกลุ่มของฟังก์ชันที่ใช้สำหรับการคำนวณเกี่ยวกับพหุนาม (polynomial) ซึ่งเป็นนิพจน์ที่สร้างจากตัวแปรอย่างน้อยหนึ่งตัวกับค่าสัมประสิทธิ์ ที่มาทำการดำเนินการด้วยวิธีการบวก ลบ คูณ หรือยกกำลัง (ต้องเป็นเลขยกกำลังที่เป็นจำนวนเต็มที่ไม่เป็นลบเท่านั้น) โดยคำสั่งที่โมดูลย่อยรองรับเหมือนกับ numpy ได้แก่

  1. ผลลัพธ์ = ulab.poly.polyval( p, x) เป็นการประเมินพหุนาม ซึ่งต้องการ 2 อาร์กิวเมนต์ที่ต้องเป็นแถวลำดับ และแถวลำดับที่เป็นผลลัพธ์จะเกิดจาก การนำค่าใน x ไปคูณกับทุกสมาชิกของ p และทำการยกกำลังของ x ด้วยลำดับของเลขยกกำลัง เช่น ต้องการทราบผลลัพธ์ของ 2*3^2+4*3^1+2*3^0 จะต้องสร้าง p เป็นแถวลำดับของ 2, 4 และ 2 และให้ x เป็น 3
  2. polyfit( x, y, a ) เป็นการคำนวณหา regression ที่ไม่เป็นเส้นตรง โดย x เป็นแถวลำดับของตัวแปรอิสระ (independent variable) y เป็นแถวลำดับของตัวแปรตาม (dependent variable) โดยจำนวนสมาชิกของ x และ y จะต้องเท่ากัน และ a คือ ดีกรีของพหุนาม
  3. polyfit( y, a ) เป็นการคำนวณหา regression ที่ไม่เป็นเส้นตรง โดย y เป็นแถวลำดับของตัวแปรตาม และ a คือดีกรีของพหุนาม

ตัวอย่างโปรแกรม1

ตัวอย่างโปรแกรม code18-16 เป็นตัวอย่างการใช้ polyval และ polyfit เพื่อคำนวณค่า ซึ่งผลลัพธ์ของการทำงานเป็นดังภาพที่ 1

# code18-16 : poly
import ulab as np
import esp32
import time

# 2*3^2+4*3^1+2*3^0 = ?
p = np.array([2,4,2])
a = np.array([3])
print('value of p(a): ', np.poly.polyval(p, a))

# 2*3^4+3*3^3+1*3^2+2*3^1+0*3^0 = ?
# 2*2^4+3*2^3+1*2^2+2*2^1+0*2^0 = ?
p = np.array([2,3,1,2,0])
a = np.array([3,2])
print('value of p(a): ',np.poly.polyval(p, a))

x = np.linspace(0,10,15)
y = np.array([0]*15,dtype=np.float)
for idx in range(15):
    y[idx] = (x[idx]*x[idx])/2.0+(esp32.hall_sensor()*(time.ticks_ms()/1000000.0))
print(x)
print(y)
print(np.poly.polyfit(x,y,2))
print(np.poly.polyfit(y,2))
ภาพที่ 1 ผลลัพะ์จาก code18-16

fft

โมดูลย่อย fft ใช้สำหรับคำนวณการแปลง (Transform) ด้วยวิธี fast Fourier และค่าอินเวิร์สของการแปลง และรองรับการทำงานของฟังก์ชัน spectrogram เช่นเดียวกับไลบรารี scipy

  1. จำนวนจริง,จำนวนจินตภาพ = np.fft.fft(x) ทำการแปลง Fourier แถวลำดับ x ให้เป็นค่าในโดเมนของความถี่ (Frequency domain)
  2. จำนวนจริง,จำนวนจินตภาพ = np.fft.fft(x,y) ทำการแปลง Fourier แถวลำดับ x และ y ให้เป็นค่าในโดเมนของความถี่
  3. แถวลำดับ1,แถวลำดับ2 = np.fft.ifft( แถวลำดับจำนวนจริง, แถวลำดับจำนวนจินภาพ ) เป็นการหาส่วนกลับของการแปลง Fourier
  4. spectrogram(x) เป็นการหาค่าผลบวกของค่ารากที่สองของจำนวนจริงกำลังสองกับจำนวนจินตภาพกำลังสองที่ได้จาก fft ของ x

ตัวอย่างโปรแกรม2

ตัวอย่างโปรแกรม code18-17 เป็นตัวอย่างการใช้งานฟังก์ชัน fft, iffft และ spectogram ซึ่งผลลัพธ์ของการทำงานเป็นดังภาพที่ 2

#coce18-17 : fft
import ulab as np
# FFT
numData = 4
x = np.linspace(0,10,numData)
print("x",x)
y = np.vector.cos(x)
print("y",y)
z = np.zeros(len(x))
print("z",z)
a,b = np.fft.fft(x)
for i in range(numData):
    print("fft(x) = {}+{}i".format(a[i],b[i]))
c,d = np.fft.fft(x,z)
for i in range(numData):
    print("fft(x,z) = {}+{}i".format(c[i],d[i]))
#
xnew = np.fft.ifft(a,b)
print("ifft(a,b)",xnew)
x2new,znew = np.fft.ifft(c,d)
print("ifft(c,d) ->x",x2new)
print("    ->z",znew)
#
a,b = np.fft.fft(y)
s = np.fft.spectrogram(y)
print(np.vector.sqrt(a*a+b*b))
print(s)
ภาพที่ 2 ผลลัพธ์จาก code18-17

filter

โมดูลย่อย filter รองรับฟังก์ชัน convole เพื่อทำการคอนโวลูต (convolution) กับแถวลำดับ 1 มิติ และรองรับฟังก์ชันการทำการฟิลเตอร์แบบ cascaded second-order ด้วยฟังก์ชัน sosfilt เช่นเดียวกับในไลบรารี scipy

  1. ผลลัพธ์ = np.filter.convolve( x, y ) คืนค่าแบบไม่ต่อเนื่อง (discrete) ของการแปลงเชิงเส้น (linear convolution) ของแถวลำดับ 1 มิติจำนวน 2 ตัว

ตัวอย่างโปรแกรม3

ตัวอย่างโปรแกรม code18-18 เป็นการใช้ฟังก์ชัน conlove ของโมดูลย่อย filter โดยผลลัพธ์ของการ convolve ระหว่าง x กับ y ได้เป็นดังภาพที่ 3

#coce18-18 : filter
import ulab as np

x = np.array([1,2,3,4,5])
y = np.array([1,10,100,1000])
print("x convolute with y = {}".format(np.filter.convolve(x,y)))

ภาพที่ 3 ผลลัพธ์จาก code18-18

สรุป

จากบทความในตอนนี้ผู้อ่านได้รู้ถึงการใช้งานฟังก์ชันต่าง ๆ ของโมดูลย่อย poly, fft และ filter พร้อมทั้งคำอธิบายวิธีการใช้งานและตัวอย่างโปรแกรม ซึ่งทีมผู้เขียนหวังว่าคงเป็นแนวทางของการนำไปใช้งานต่อไป และที่สำคัญ ฟังก์ชันกาทำงานต่าง ๆ สามารถนำไปใช้กับไลบรารีของ numpy ในภาษาไพธอนได้ ยกเว้น fft ที่ผู้อ่าจะต้องแปลงค่าจำนวนจริงและจำนวนจินตภาพ เนื่องจาก ulab ไม่รองรับการใช้ตัวเลขเชิงซ้อน

สุดท้ายนี้หวังว่าผู้อ่านจะได้สนุกกับการเขียนโปรแกรมต่อไปครับ

เอกสารอ้างอิง

  1. numpy.polyval
  2. numpy.polyfit
  3. numpy.convolve

(C) 2020, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2020-11-11
ปรับปรุงเมื่อ 2021-08-16