Tag Archives: Python

ทางเลือกในการตัดคำภาษาไทย ด้วย Python

ประโยคในภาษาไทยไม่ได้มีการเว้นวรรคระหว่างคำ การจะตัดคำในประโยคจึงต้องใช้ algorithm มาหาว่าตรงไหนเป็นคำ แล้วจึงตัด ก็ไปเจออยากน้อยสองที่ซึ่งใช้ได้ กับภาษา Python คือ PyThaiNLP และ deepcut ท่าทาง machine learning ได้ประโยชน์ในงานนี้ล่ะครับ

PyThaiNLP
https://python3.wannaphong.com/2017/05/pythainlp-%e0%b9%82%e0%b8%a1%e0%b8%94%e0%b8%b9%e0%b8%a5-nlp-%e0%b8%a0%e0%b8%b2%e0%b8%a9%e0%b8%b2%e0%b9%84%e0%b8%97%e0%b8%a2%e0%b9%83%e0%b8%99-python.html
https://github.com/wannaphongcom/pythainlp

ผมใช้กับ Python 3 นะครับ ติดตั้งโดยสั่ง

pip3 install pythainlp

ทดลองสคริป Python (จริงๆ ก็ทำคล้ายๆ ของเจ้าของผลงานครับ)

from pythainlp.segment import segment
s=segment('ฉันรักภาษาไทยเพราะฉันเป็นคนไทย')
print(s)

ได้ออกมาว่า

['ฉัน', 'รัก', 'ภาษา', 'ไทย', 'เพราะ', 'ฉัน', 'เป็น', 'คน', 'ไทย']

ถ้าเป็น Python 2 ก็ใช้ได้เหมือนกันครับ แต่ต้องระบุสตริงเป็น Unicode ด้วย ใส่ u ข้างหน้าสตริง (u’ฉันรักภาษาไทยเพราะฉันเป็นคนไทย’) ส่วนผลลัพธ์เมื่อพิมพ์อาจจะออกมาเป็นโค้ดนะครับ เช่น u’\u0e09\u0e31\u0e19′ คือ ‘ฉัน’

deepcut
https://www.facebook.com/groups/988867541235062/permalink/1258831837571963/
https://github.com/rkcosmos/deepcut

ติดตั้งบน Python 3 บ้าง

pip3 install deepcut

ซึ่งรอนานเอาเรื่องเลยครับ จากนั้นก็ทดลองใช้งาน

from deepcut import tokenize 
tokenize('ฉันรักภาษาไทยเพราะฉันเป็นคนไทย')

ก็ได้ผลลัพธ์เหมือนกัน เลยลองใช้ทั้งสอบแบบในสคริปเดียวกันดู
(พึ่งเห็นว่ายังไม่ได้คอมไพล์ TensorFlow ให้ไปใช้ความสามารถของชุดคำสั่ง SSE 4.1, SSE 4.2 และ AVX อันที่จริง GPU ค่ายเขียวในเครื่องก็มีนะครับ แต่ต้องสมัครลงทะเบียน cuDNN)

แล้วก็ รวมตัวเลือก https://github.com/kobkrit/nlp_thai_resources/blob/master/README.md

Advertisements

ลองภาษา R แบบขำๆ เร็วๆ

ขอเขียนแบบตีหัวเข้าบ้านเลยนะครับ ใช้แนวทางจาก https://stats.idre.ucla.edu/r/dae/logit-regression/ ทดลองทำ Logistic Regression โดยติดตั้ง R ด้วยวิธีจาก https://www.r-bloggers.com/how-to-install-r-on-linux-ubuntu-16-04-xenial-xerus/

ก็สั่ง

$ wget https://stats.idre.ucla.edu/stat/data/binary.csv
$ Rscript -e " mydata <- read.csv(\"binary.csv\");  mylogit <- glm(admit ~ gre + gpa , data = mydata, family = \"binomial\"); summary(mylogit)"

ได้ผลลัพธ์ออกมาเป็น

Call:
glm(formula = admit ~ gre + gpa, family = "binomial", data = mydata)

Deviance Residuals:
Min       1Q   Median       3Q      Max
-1.2730  -0.8988  -0.7206   1.3013   2.0620

Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -4.949378   1.075093  -4.604 4.15e-06 ***
gre          0.002691   0.001057   2.544   0.0109 *
gpa          0.754687   0.319586   2.361   0.0182 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

Null deviance: 499.98  on 399  degrees of freedom
Residual deviance: 480.34  on 397  degrees of freedom
AIC: 486.34

Number of Fisher Scoring iterations: 4

แถม pandas กับภาษา Python ซะหน่อย ไปเจอมาจาก http://blog.yhat.com/posts/logistic-regression-and-python.html ดูเหมือนจะใช้ csv file เดียวกัน แต่อยู่คนละ path

ติดตั้ง pandas ก่อน ผมลง pip ไปแล้ว ก็

$ sudo pip install pandas

จากนั้น Python ใส่สคริป

import pandas as pd

df = pd.read_csv("binary.csv")
print df.head()

ได้ผลเหมือนตัวอย่าง

   admit  gre   gpa  rank
0      0  380  3.61     3
1      1  660  3.67     3
2      1  800  4.00     1
3      1  640  3.19     4
4      0  520  2.93     4

แก้ Euler Project 551

ไปเจอปัญหาจาก Euler Project ข้อ 551 สรุปได้ว่า กำหนดลำดับ a(0), a(1), a(2), … โดย

a(n) = d(a(n-1)) + d(a(n-2)) + d(a(n-3)) + .. + d(a(1)) + d(a(0))

โดย a(0)=1 และ d(n) คือการเอาตัวเลขโดดของทุกหลักของเลข n มาบวกกัน (sum of digits) โจทย์ให้หาค่าของ a(1015)

ดูดีๆ จะเห็นว่า a(n) = d(a(n-1)) + a(n-1) ด้วยเช่นกัน ถ้าจะแก้แบบ recursive งานนี้ถ้าจะแก้กันง่ายๆ ตรงไปตรงมา เขียนด้วยภาษาสคริป Python ได้ว่า

def d(n):
    r = 0
    while n:
        r += n % 10
        n //= 10
    return r   

a=1
for i in xrange(1, 10**6):
    a+=d(a)

ซึ่งคำนวณถึงแค่ a(106) ก็ได้ค่า 31054319 ตรงกับที่ตัวอย่างให้มา ถ้าจะเอาให้ถึงตามโจทย์ สงสัยต้องหาทางแก้ non-homogeneous linear recurrence relation ให้ได้ก่อนครับ ก็อาจจะได้สมการที่มียกกำลัง n ออกมา หรืออาจต้องหาทางว่า มีความสัมพันธ์ที่จะย่อย n ให้ลงไปเป็เท่าๆ ตัว เช่น a(2n) = … ที่มี a(n..)

ปล. มีคนแจก source code วิธีแก้ในภาษา Python แล้วครับ ผมรันดูแล้วเสร็จในแป็ปเดียว https://git.icpc-camp.org/ftiasch/acm-icpc/blob/6d1d563a1dea39b8a8f525c836c5f3b0a243678b/project-euler/p551/p551.py

LoPy บอร์ดจิ๋วโปรแกรมด้วยภาษา MicroPython

อีกบอร์ดจิ๋วในยุคที่มีการพูดถึง IoT อยู่บ่อยๆ ครับ LoPy ผลิตโดย Pycom ซึ่งเคยสร้าง WiPy มาก่อนแล้ว โปรแกรมด้วยภาษา MicroPython ระดมทุนใน Kickstarter สำเร็จไปแล้ว และดูเหมือนตอนนี้ของจะขาด

ข้อมูลคร่าวๆ

  • Bluetooth Low Energy
  • Wi-Fi 802.11b/g/n 16Mbps
  • สื่อสารแบบ LoRa ด้วยคลื่นวิทยุความถี่ 868 MHz หรือ 915MHz
  • RAM: 256 KB
  • Flash ภายใน 1MB, ภายนอก 4MB
  • GPIO 25 ขา และมี RTC
  • มี 2 x UART, SPI, I2C, DMA, I2S

 

 

แก้ Euler Project 501

มีปัญหา Euler Project หมายเลข 501 ให้หาจำนวนตั้งแต่ 1 ถึง 1012 ว่ามีกี่ตัว ที่จำนวนตัวหารซึ่งหารแล้วลงตัวของมันนั้น มีเท่ากับ 8 ตัว

ถ้าใช้วิธีวนลูปตรงๆ คืิอไล่เลข 1 ถึง 1012 ที่ละตัว เอามาหารด้วยเลข 1 จนถึงตัวมันเอง แล้วนับว่ามีหารลงตัวแปดตัวหรือไม่ ช้าแน่ ต้องหาวิธีอื่น โดยใช้หลักคณิตศาตร์มาช่วย คือเมื่อเอาตัวเลขมาแยกตัวประกอบ ให้กลายเป็นผลคูณของจำนวนเฉพาะ ถ้าจำนวนเฉพาะมีซ้ำกันให้เขียนเป็นเลขยกกำลัง จำนวนของตัวหารที่ลงตัว เท่ากับเอาเลขชี้กำลังของแต่ละจำนวนเฉพาะนั้น มาบวกเพิ่มอีกหนึ่งแล้วคูณกัน

เช่น 24 = 2331 เลขชี้กำลังมี 3 และ 1 เอามาบวกเพิ่มอีก 1 จะได้ 4 และ 2 เมื่อคูณกันได้ 8 คือมีจำนวนตัวหารเท่ากับ 8 ตัว (24 นี้มี 1, 2, 3, 4, 6, 8, 12, 24) โดยเลข 8 สามารถได้มาจากการคูณ 8×1, 4×2, 2×4, 2x2x2 ถ้าเราจะไล่หาจำนวนที่มีตัวหารลงตัวแปดตัวโดยทำย้อนไป โดยเอาจำนวนเฉพาะมายกกำลังและคุณกัน โดยเลขชี้กำลังต้องเข้ากับเงื่อนไขที่จะทำให้มีตัวหารลงตัวแปดตัว ก็จะมีได้สี่กรณี

p7
p3q1
p1q3
p1q1r1

โดย 1 < p < q < r และทั้งสามเป็นจำนวนเฉพาะ

ลอง coding คร่าวๆ

##

import itertools
import math

def is_prime(num):
    if num < 2:
        return False
    for x in range(2, int(math.sqrt(num))+1):
        if num % x == 0:
            return False
    else:
        return True

def fd0(p, lmbd):
    r=0
    for x in (itertools.combinations(p, lmbd.__code__.co_argcount)):
        if lmbd(*x):
            r+=1
    return r
    
nn=100
lp=list(filter(is_prime, range(1, nn+1)))
a=fd0(lp, lambda x: x**7 <= nn)
b=fd0(lp, lambda x, y: x**3 *y <= nn)
c=fd0(lp, lambda x, y: y**3 *x <= nn)
d=fd0(lp, lambda x, y, z: x*y*z <= nn)
t1=a+b+c+d

nn=1000
lp=list(filter(is_prime, range(1, nn+1)))
a=fd0(lp, lambda x: x**7 <= nn)
b=fd0(lp, lambda x, y: x**3 *y <= nn)
c=fd0(lp, lambda x, y: y**3 *x <= nn)
d=fd0(lp, lambda x, y, z: x*y*z <= nn)
t2=a+b+c+d


##

แต่ถ้าทำถึงเลข 1012 ยังช้าอยู่นะครับ ต้องหาทางออกจากวนลูปเอง เมื่อการคูณเกินจำนวนที่กำหนดไว้

##
def is_prime(num):
    if num < 2:
        return False
    x=2
    while x*x<=num:
        if num % x == 0:
            return False
        x+=1
    return True

nn=10**6
lp=list(filter(is_prime, range(1, nn//6 +2)))
lp.sort()

r=0
for i in range(len(lp)):
    if lp[i]**7 > nn:
        break
    else:
        r+=1

for i in range(len(lp)):
    for j in range(i+1, len(lp)):
        if lp[i]**3 *lp[j] > nn:
            break
        else:
            r+=1

for i in range(len(lp)):
    for j in range(i+1, len(lp)):
        if lp[j]**3 *lp[i] > nn:
            break
        else:
            r+=1

for i in range(len(lp)):
    for j in range(i+1, len(lp)):
        if lp[i]*lp[j] > nn:
            break
        for k in range(j+1, len(lp)):
            if lp[i]*lp[j]*lp[k] > nn:
                break
            else:
                r+=1
          
print(r)
##

Computer Unbeatable Hangman Game (Improved)

Improved my Python Code for participation in Weekend Programming Challenge Issue-8 (solutions).

Or improved code http://pastebin.com/raw.php?i=6sCKNae3

import sys
import string
import fileinput
import random
import re
from string import maketrans

# file wordlower.txt contains one word in one line
# to filter only lowerletter 
# grep [a-z] < words.txt > wordlower.txt

file = [line.rstrip('\n') for line in fileinput.input("wordlower.txt")]
#print file[0]
#print file[len(file)-1]
rand = random.Random()
w1 = file[int(rand.random() * len(file))]

#improvement: create list only the same len of random word without itself
#list file_only_the_same_len is list of words for cheating
file_only_the_same_len = [i for i in file if len(i)==len(w1) and i!=w1]

w2 = '.'*len(w1) # len of w1
count = 10
t1 = 'abcdefghijklmnopqrstuvwxyz'
t2 = '.'*len(t1)
usedletter = []

# maskword() removes char c that must be hidden from t1 
# and returns w only char that must be disclosed
def maskword(w, c):
    global t1
    global t2
    t2 = t2[:-1]
    t1 = t1.replace(c, '')
    trantab = maketrans(t1, t2)
    return str.translate(w, trantab)

while True:
    #print "'%s'" % w1 # debug or real cheat :D
    print "Guess word '%s'. Count remain=%d" % (w2, count)
    print "Used letters %s" % usedletter
    if w1 == w2:
        print "You win"
        break

    l = raw_input('Enter guess letter ')
    l = string.lower(l[:1]) #only 1-st lowercase letter
    if any(l in s for s in usedletter):
        print "%s already choosen" % l
        continue
    else:
        usedletter.append(l)
        file_only_the_same_len = [i for i in file_only_the_same_len if not l in i]

    if string.find(w1, l) == -1: #letter not found, no need to change w1
        count -= 1
        print "No %s letter in that word."  % l
        if count <= 0:
            print "You lose. Answer is %s" % w1
            break
        
        continue #letter not found -> continue loop

    # w1 contains that guese letter
    # cheating here
    # by changing (if possible) w1 so that it does not contain letter l
    # and does not contain letters that in usedletter
    # and masking still like w2 (the same string len too

    rex = re.compile("^%s$" % w2)
    for w3 in file_only_the_same_len:
        #print "%s w3=%s cheatlist=%d " % (w1, w3, len(file_only_the_same_len)) # debug printing
        if rex.match(w3): 
            w1 = w3 # todo w3 should not contain letter in usedletter 
            break

    #print "'%s' (cheat)" % w1 # debug or real cheat :D
    if string.find(w1, l) == -1: #check again if letter not found
        count -= 1
        print "No %s letter in that word."  % l
        if count <= 0:
            print "You lose. Answer is %s" % w1
            break

    else:
        print "Contains %s" % l
        w2 = maskword(w1, l)

Using MOD-RFID1356 in Serial Mode by Python

This continues from previous post. Now I write small Python script that uses serial port by pySerial library. Installation pySerial on Raspberry Pi just using command

pip install  pyserial

Script continues to read from /dev/ttyACM0 device that is connected with MOD-RFID1356. Be careful punctuation in Python. Please read PEP8 first.

import serial

ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0)
while True:
    line = ser.readline()
    if (line):
        print (line)

or get this script from http://pastebin.com/5X9Dpkx0