Generating Python Code for Matrix Inner Product in SQLite Database

10Feb11

Pada waktu event wordcampid yang lalu saya sempat menulis kode untuk melakukan pencarian citra dari database (image retrieval). Kodenya ditulis ketika agak senggang atau ketika topik pembicaraannya tidak terlalu menarik. Saya menggunakan fitur berupa matriks 8×8 yang disimpan dalam database SQLite. Pada intinya saya berniat melakukan inner (dot) product melalui pernyataan SQL (supaya sekalian diurutin dan dibatasi top N :D ). Awalnya senang-senang saja, lama-lama saya bosan juga kalau harus mengetik 64 field dan 64 parameter untuk setiap fungsi (ada 3 fungsi yaitu mendefinisikan table, insert, dan find). jadi totalnya 64 x 5 = 320 field harus saya ketik manual. Saya tidak pakai perulangan karena malas melihat kode berisi penempelan string kala itu. Hari berikutnya akhirnya saya menulis kode untuk mengotomatisasi pekerjaan tersebut (bayangkan kalau saya ubah eksperimennya jadi fitur berukuran 12×12 atau 25×25).

Kode yang saya tulis ketika dijalankan akan menghasilkan file teks berisi kode python yang spesifik dengan dimensi matriks yang menjadi parameter.

def genmat(la):
    result = []
    for i in xrange(0,la[0]):
        if len(la)==1:
            result += [["%s" % i]]
        else:
            row = ["%s" % i]
            tmp = genmat(la[1:])
            for x in tmp:
                result += [row+x]
    return result

def setup(n, output="Test", tablename="vec", cols=[], classprefix="DocSearch"):
    classname=classprefix+output
    fpy = open(output+".py", "w")
    if len(cols)==0:
        cols = [("id", "INTEGER PRIMARY KEY"), ("desc", "CHAR(255)")]
    lcols = []
    try:
        dim = len(n)
        vcols = genmat(n)
    except:
        dim = 1
        vcols = genmat([n])
    for f in vcols:
        lcols += [("v"+"_".join(f), "DOUBLE NOT NULL")]
    scols = ", ".join(["%s %s" % (c, t) for c, t in lcols+cols])
    fpy.write("""
import sqlite3

class %s:
    def __init__(self, dbname="db%s.db"):
        self.db = dbname
        self.con = sqlite3.connect(self.db)
        
    def setup(self):
        self.con.execute("CREATE TABLE %s (%s)")
        self.con.commit()
    """ % (classname, output, tablename, scols))

    acols = ", ".join(["%s" % (c) for c, t in cols])
    icols = ", ".join(["%s" % (c) for c, t in lcols+cols])
    ivcols = ", ".join(["?"]*(len(lcols)+len(cols)))
    _ipcols = []
    for f in vcols:
        _ipcols += ["f"+"".join(["["+v+"]" for v in f])]
    ipcols = ", ".join(_ipcols)
    fpy.write("""    
    def insert(self, f, %s):
        self.con.execute("INSERT INTO %s (%s) VALUES (%s)" %s (%s, %s))
        self.con.commit()
    """ % (acols, tablename, icols, ivcols, "%", ipcols, acols))
    
    qcols = ", ".join(["%s*%s" % (c, "?") for c, t in lcols])
    fpy.write("""    
    def query(self, f):
        c = self.con.cursor()
        c.execute("SELECT (%s) as dot, %s FROM %s ORDER BY dot DESC" %s (%s))
        rows = c.fetchall()
        return rows
    """ % (qcols, acols, tablename, "%", ipcols))
    
    fpy.write("""

if __name__=="__main__":
    search = %s()
    search.setup()
    """ % (classname))
    fpy.close()
   
if __name__=="__main__":
    setup(3, "1x3")
    setup([2,2], "2x2")
    setup([8,8], "8x8")
    #print genmat([2,2])
    

Kode di atas juga berisi contoh penggunaan fungsi untuk berbagai dimensi (misal 1xn, mxn, mxnxsxtx…xz). Contoh keluaran untuk matriks 2×2 seperti berikut:

import sqlite3

class DocSearch2x2:
    def __init__(self, dbname="db2x2.db"):
        self.db = dbname
        self.con = sqlite3.connect(self.db)
        
    def setup(self):
        self.con.execute("CREATE TABLE vec (v0_0 DOUBLE NOT NULL, v0_1 DOUBLE NOT NULL, v1_0 DOUBLE NOT NULL, v1_1 DOUBLE NOT NULL, id INTEGER PRIMARY KEY, desc CHAR(255))")
        self.con.commit()
        
    def insert(self, f, id, desc):
        self.con.execute("INSERT INTO vec (v0_0, v0_1, v1_0, v1_1, id, desc) VALUES (?, ?, ?, ?, ?, ?)" % (f[0][0], f[0][1], f[1][0], f[1][1], id, desc))
        self.con.commit()
        
    def query(self, f):
        c = self.con.cursor()
        c.execute("SELECT (v0_0*?, v0_1*?, v1_0*?, v1_1*?) as dot, id, desc FROM vec ORDER BY dot DESC" % (f[0][0], f[0][1], f[1][0], f[1][1]))
        rows = c.fetchall()
        return rows
    

if __name__=="__main__":
    search = DocSearch2x2()
    search.setup()
    

Kode di atas masih bisa dikembangkan lagi, misalnya untuk interface basisdata lain seperti mysql atau postgreS atau menggunakan SQLAlchemy. Oya, saya juga lupa, kode untuk Update belum ada :D .



No Responses Yet to “Generating Python Code for Matrix Inner Product in SQLite Database”

  1. Tinggalkan sebuah Komentar

Tinggalkan Balasan

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Ubah )

Twitter picture

You are commenting using your Twitter account. Log Out / Ubah )

Facebook photo

You are commenting using your Facebook account. Log Out / Ubah )

Connecting to %s


Ikuti

Get every new post delivered to your Inbox.

Bergabunglah dengan 271 pengikut lainnya.