Thứ Hai, 17 tháng 12, 2018

Giới thiệu thuật toán Kd Trees (Nearest neighbour search)

Sơ lược:

 
  • Kd-trees dùng để tìm kiếm các dữ liệu gần, liên quan nhất (neighbouring data points) trong miền không gian 2 chiều, hoặc nhiều chiều.
  • Kd-trees thuộc họ Nearest neighbor (NN) search.

Tóm tắt:

  1. Cách build Kd-trees từ tranning data:
  • chọn 1 chiều random, tìm toạ độ trung bình, chia data theo toạ độ đó, lặp lại.
  1. Cách tìm các dữ liệu liên quan cho point (7,4)
  • tìm các phân vùng chứa điểm (7,4)
  • so sánh khoảng cách điểm đó tới tất cả các điểm trong phân vùng để chọn cái gần nhất.

Chi tiết:

  1. Code build tree:
from collections import namedtuple
from operator import itemgetter
from pprint import pformat
 
class Node(namedtuple('Node', 'location left_child right_child')):
 
    def __repr__(self):
        return pformat(tuple(self))
 
def kdtree(point_list, depth=0):
    """ build K-D tree
    :param point_list list of input points
    :param depth      current tree's depth
    :return tree node
    """
 
    # assumes all points have the same dimension
    try:
        k = len(point_list[0])
    except IndexError:
        return None
 
    # Select axis based on depth so that axis cycles through
    # all valid values
    axis = depth % k
 
    # Sort point list and choose median as pivot element
    point_list.sort(key=itemgetter(axis))
    median = len(point_list) // 2         # choose median
 
    # Create node and construct subtrees
    return Node(
        location=point_list[median],
        left_child=kdtree(point_list[:median], depth + 1),
        right_child=kdtree(point_list[median + 1:], depth + 1)
    )
  1. Từ tree có được, ta build hàm tìm các điểm neighbour của một điểm cho trước:
Cách search như sau:
  • Bắt đầu root node, move qua các nhánh một cách đệ quy.
  • Trong khi lướt qua các nhánh, thuật toán sẽ lưu lại node có khoảng cách ngắn nhất với khoảng cách chưa target point (là điểm cần tìm neghibour), được gọi là current best (tốt nhất hiện tại)
  • Nếu node hiện tại gần target point hơn current best, nó sẽ trở thành current best.
  • Trong khi di chuyển nó sẽ check xem, với điểm current best ở nhánh trái thì distance best(khoảng cách từ target point tới current best) có ngắn hơn khoảng cách từ target point tới bờ phân chia hay không, nếu ngắn hơn tức là bên nhánh trái đã cho kết quả tốt nhất và ta không cần tìm tiếp bên phải, nếu dài hơn tức là có lẽ sẽ có 1 điểm nào đó bên phải cho khoảng cách tới target point tốt hơn nên ta phải tiếp tục loop qua các nhánh bên phải. 
  • Với mỗi nhánh, thuật toán hoàn thành cho tới khi chạm leaf node.
Code
nearest_nn = None           # nearest neighbor (NN)
distance_nn = float('inf')  # distance from NN to target
 
def nearest_neighbor_search(tree, target_point, hr, distance, nearest=None, depth=0):
    """ Find the nearest neighbor for the given point (claims O(log(n)) complexity)
    :param tree         K-D tree
    :param target_point given point for the NN search
    :param hr           splitting hyperplane
    :param distance     minimal distance
    :param nearest      nearest point
    :param depth        tree's depth
    """
 
    global nearest_nn
    global distance_nn
 
    if tree is None:
        return
 
    k = len(target_point)
 
    cur_node = tree.location         # current tree's node
    left_branch = tree.left_child    # its left branch
    right_branch = tree.right_child  # its right branch
 
    nearer_kd = further_kd = None
    nearer_hr = further_hr = None
    left_hr = right_hr = None
 
    # Select axis based on depth so that axis cycles through all valid values
    axis = depth % k
 
    # split the hyperplane depending on the axis
    if axis == 0:
        left_hr = [hr[0], (cur_node[0], hr[1][1])]
        right_hr = [(cur_node[0],hr[0][1]), hr[1]]
 
    if axis == 1:
        left_hr = [(hr[0][0], cur_node[1]), hr[1]]
        right_hr = [hr[0], (hr[1][0], cur_node[1])]
 
    # check which hyperplane the target point belongs to
    if target_point[axis] <= cur_node[axis]:
        nearer_kd = left_branch
        further_kd = right_branch
        nearer_hr = left_hr
        further_hr = right_hr
 
    if target_point[axis] > cur_node[axis]:
        nearer_kd = right_branch
        further_kd = left_branch
        nearer_hr = right_hr
        further_hr = left_hr
 
    # check whether the current node is closer
    dist = (cur_node[0] - target_point[0])**2 + (cur_node[1] - target_point[1])**2
 
    if dist < distance:
        nearest = cur_node
        distance = dist
 
    # go deeper in the tree
    nearest_neighbor_search(nearer_kd, target_point, nearer_hr, distance, nearest, depth+1)
 
    # once we reached the leaf node we check whether there are closer points
    # inside the hypersphere
    if distance < distance_nn:
        nearest_nn = nearest
        distance_nn = distance
 
    # a nearer point (px,py) could only be in further_kd (further_hr) -> explore it
    px = compute_closest_coordinate(target_point[0], further_hr[0][0], further_hr[1][0])
    py = compute_closest_coordinate(target_point[1], further_hr[1][1], further_hr[0][1])
 
    # check whether it is closer than the current nearest neighbor => whether a hypersphere crosses the hyperplane
    dist = (px - target_point[0])**2 + (py - target_point[1])**2
 
    # explore the further kd-tree / hyperplane if necessary
    if dist < distance_nn:
        nearest_neighbor_search(further_kd, target_point, further_hr, distance, nearest, depth+1)
  1. Chạy thử:

Dùng với scikit-learn:

  1. Dùng sklearn:
>>> import numpy as np
>>> np.random.seed(0)
>>> X = np.random.random((10, 3))  # 10 points in 3 dimensions
>>> tree = KDTree(X, leaf_size=2)              
>>> dist, ind = tree.query([X[0]], k=3)                
>>> print(ind)  # indices of 3 closest neighbors
[0 3 1]
>>> print(dist)  # distances to 3 closest neighbors
[ 0.          0.19662693  0.29473397]



Cảm ơn các bạn đã đọc, happy learning 😄

Reference:

Đôi nét về goroutine

Goroutine

Một trong những điểm nổi bật của Golang là goroutine, nó có gì nổi bật để khiến cho cocurrency trong Go trở nên dễ dàng như vậy

Cấu trúc:

  • Một goroutine được khởi tạo với chỉ 2KB trong stack size
  • Goroutines chứa trong ít stack size nhưng có thể tự grow khi cần, thông thường sẽ có hàng trăm nghìn goroutines bên trong chương trình của bạn. Điều này cho phép lập trình viên use concurrency structure bên trong chương trình mà không cần quan tâm có bị overhead hay không.
  • Goroutines chính là function executing concurrently cùng lúc với các goroutines khác trên cùng địa chỉ space
  • Cấu trúc code:
struct P
{
    Lock;
    G *gfree; // freelist, moved from sched
    G *ghead; // runnable, moved from sched
    G *gtail;
    MCache *mcache; // moved from M
    FixAlloc *stackalloc; // moved from M
    uint64 ncgocall;
    GCStats gcstats;
    // etc
    ...
};

P *allp; // [GOMAXPROCS]

type schedt struct {
 glock mutex
 gfree *g
     Ngfree int32
}

Go scheduler.

Go Scheduler có 3 thành phần chính:
  • Hình tam giác đại diện cho OS thread, thread là luồng thực thi được quản lí bởi OS.
  • Hình tròn đại diện cho goroutine, nó bao gồm stack, pointer, và các thông tin quan trọng cho việc quản lí scheduling goroutines.
  • Hình chữ nhật đại diện cho context của scheduling. Nó được coi như phiên bản single thread trong golang.
  • Như các bạn thấy có 2 loại queue trong golang là global queue và local queue, và mỗi P duy trì một chuỗi G đang chạy.
  • Để thực thi được goroutine, M cần được trong context của P. Machine, sau đó sẽ pop goroutine ra khỏi queue P và thực thi code.
  • Khi chúng ta tạo thực thi cuộc gọi: go func(), thì nó sẽ được đặt vào trong P queue. Và đây là mấu chốt trong thuật toán đánh cắp công việc (work-stealing scheduling algorithm), cái mà sẽ chạy khi M kết thúc thực thi một số G và thử một số G khác bên ngoài queue hiện tại, nếu queue hiện tại mà rỗng, nó sẽ random chọn P(gọi là P1) khác và thử đánh cắp một nửa số goroutine G khỏi queue P1.

Tại sao chúng ta lại cần context P.

  • Lí do cho việc có context P là để đánh cắp số lượng Goroutine G từ một threads khác nếu thread đang chạy bị block vì một lí do nào đó.
  • Ví dụ chúng ta cần block thread vì cần chờ người dùng nhập input (syscall) hay connect với DB chẳng hạn. Một thread không thể vừa bị block vừa thực thi code được, nên chúng ta cần khái niệm context để giữ việc scheduling.
Reference:

Thứ Bảy, 16 tháng 7, 2016

[Window phone] Giới thiệu ứng dụng quản lí động vật cưng.

Nhằm giúp những người có sở thích nuôi thú cưng có thể quản lí mọi việc liên quan đến động vật cưng của mình, mình đã đưa ra ứng dụng quản lí mọi vấn đề liên quan đến thú cưng.
Ứng dụng có các chức năng :

  • Quản lí, đặt lịch hẹn giờ báo về các hoạt động hằng ngày như cho ăn, dắt đi vệ sinh, hay tắm cho vật nuôi
  • Lưu thông tin các thú cưng của mình.
  • Quản lí giá cả các đồ ăn, vật phẩm của thú cưng.
  • Lưu lại các âm thanh để gọi thú cưng.
  • Quản lí các liên lạc bằng email và phone tới những người liên quan tới việc chăm sóc thú cưng như bác sĩ, cửa hàng bán thức ăn.
Sau đây là một số hình ảnh của ứng dụng:

[Windowphone] Giới thiệu ứng dụng đọc tin RSS

Đây là ứng dụng đọc tin tức dựa trên các mẫu tin rút gọn gọi là RSS (Định nghĩa Wiki RSS), giúp bạn đọc các tin tức một cách nhanh chóng, tổng thể mà không cần đọc hết bài viết.

Ứng dụng có các chức năng:

  • Liệt kê các danh sách các báo phổ biến hiện nay.
  • Hiển thị các mẩu tin tức nhỏ liên quan tới báo đó dựa trên phân loại nội dung.
  • Đọc tin dựa trên các phân loại nội dung của báo.
  • Đọc các tin rút gọn của tin tức.
  • Di chuyển tới website để đọc tin đầy đủ.
Sau đây là một số hình ảnh của ứng dụng.



[Window phone] Giới thiệu ứng dụng tra câu việt anh

Dựa vào website http://tracau.vn/ và các API được họ cung cấp, tôi đã làm ra một ứng dụng trên nền window phone giúp mọi người dễ dàng sử dụng tính năng này. Ứng dụng có các tính năng cơ bản sau:

  • Tra các câu tiếng anh dựa trên từ ngữ được tìm kiếm, kể cả bạn gõ tiếng việt hay tiếng anh.
  • Phát âm các câu đó.
  • Có thể lưu lại các câu ưa thích dựa trong kết quả tìm hiểu.
  • Xem lại các câu ưa thích và có thể xóa bỏ nó.
  • Xem lại lịch sử tra câu, các từ đã tra dựa theo ngày.
  • Có phần giới thiệu thông tin tác giả.
Một số hình ảnh về ứng dụng.



Thứ Bảy, 25 tháng 4, 2015

Sử dụng skrollr.js tạo hiệu ứng parallax scrolling

Đây là thư viện rất tuyệt vời để tạo hiệu ứng này vì chúng không yêu cầu phải biết javascript , kinh nhỉ .Đầu tiên là lí thuyết đầy đủ các bạn tham khảo tại đây nha:
https://github.com/Prinzhorn/skrollr
Tiếp theo là example:
File index.html:
<html>
<head>
<title>Test Parallax</title>

<link rel="stylesheet" type="text/css" href="css/me.css">

<script type="text/javascript" src="js/jquery-1.11.2.js"></script>
    <script type="text/javascript" src="js/skrollr.js"></script>
</head>
<body>

<section id="slide-1" class="homeSlide">
    <div class="bcg"
        data-center="background-position: 50% 0px;"
        data-top-bottom="background-position: 50% -100px;"
        data-anchor-target="#slide-1"
    >
        <div class="hsContainer">
            <div class="hsContent"
                data-center="bottom: 200px; opacity: 1"
                data-top="bottom: 1200px; opacity: 0"
                data-anchor-target="#slide-1 h2"
            >
                <h2>Simple parallax scrolling is...</h2>
            </div>
        </div>
    </div>
</section>
<section id="slide-2" class="homeSlide">
    <div class="bcg"
        data-center="background-position: 50% 0px;"
        data-top-bottom="background-position: 50% -100px;"
        data-bottom-top="background-position: 50% 100px;"
        data-anchor-target="#slide-2"
    >
        <div class="hsContainer">
            <div class="hsContent"
                data-center="opacity: 1"
                data-center-top="opacity: 0"
                data--100-bottom="opacity: 0;"
                data-anchor-target="#slide-2"
            >
                <h2>great for story telling websites.</h2>
            </div>
        </div>
    </div>
</section>
<section id="slide-3" class="homeSlide">
    <div class="bcg"
        data-center="background-position: 50% 0px;"
        data-top-bottom="background-position: 50% -100px;"
        data-bottom-top="background-position: 50% 100px;"
        data-anchor-target="#slide-3"
    >
        <div class="hsContainer">
            <div class="hsContent"
                data--50-bottom="opacity: 0;"
                data--200-bottom="opacity: 1;"
                data-center="opacity: 1"
                data-200-top="opacity: 0"
                data-anchor-target="#slide-3 h2"
            >
                <h2>Now go and create your own story</h2>
            </div>
        </div>
    </div>
</section>
<section id="slide-4" class="homeSlide">
    <div class="bcg"
        data-center="background-position: 50% 0px;"
        data-top-bottom="background-position: 50% -100px;"
        data-bottom-top="background-position: 50% 100px;"
        data-anchor-target="#slide-4"
    >
        <div class="hsContainer">
            <div class="hsContent"
                data-bottom-top="opacity: 0"
                data-25p-top="opacity: 0"
                data-top="opacity: 1"
                data-anchor-target="#slide-4"
            >
                <h2>and share mine.</h2>
            </div>
        </div>
    </div>
</section>
<div id="skrollr">
  <div id="footne" class="gap">
   <div class="container">
     <div class="inner-container">
          <p>Hello word</p>
     </div>
   </div>
 </div>
 <div id="foolne1" class="gap">
   <div class="container">
     <div class="inner-container">
          <p>the gioi mo ra nhe</p>
     </div>
   </div>
 </div>
</div>

<script type="text/javascript">
    skrollr.init({
        smoothScrolling: false,
        mobileDeceleration: 0.004
    });
    </script>
</body>
</html>
File me.css:


Thứ Bảy, 1 tháng 2, 2014

Chương trình Python đăng nhập tự động qhonline.info

# -*- coding: utf-8 -*-

import re
import mechanize
import time


br = mechanize.Browser()
br.open("http://www.qhonline.info/forum/forum.php")

# follow second link with element text matching regular expression
br.select_form(nr=0)
br.set_all_readonly(False)    # allow everything to be written to
br.set_handle_robots(False)   # ignore robots
br.set_handle_refresh(True)
# User credentials
br.form['vb_login_username'] = '...............'
br.form['vb_login_password'] = '...............'
br.submit()
#br.click_link(href='http://www.qhonline.info/forum/forum.php')
for link in br.links():
    print link.text, link.url
    br.follow_link(link)

print  br.response().read()

br.follow_link(url="forumdisplay.php/3-Y-kien-gop-y")

br.follow_link(url="newthread.php?do=newthread&f=3")


form = br.select_form("vbform")
br.set_all_readonly(False)    # allow everything to be written to
br.set_handle_robots(False)   # ignore robots
br.set_handle_refresh(True)
for control in br.form.controls:
    if control.name == 'sbutton':
        control.value = 'ok'
        break
br.form['subject'] = 'Chống spam thôi các mod ơi'
br.form['message'] = 'Dạo này spam cháy cả forum rùi,mấy mod ăn tết cũng nên xem lại diễn đàn cái,ọc '
br.submit(name='sbutton', label='ok')