Sunday 6 August 2017

Java reflection

1. Giới thiệu về java reflection

Java reflection là một tính năng của java, cho phép chương trình có thể biết được thông tin của một lớp(các thuộc tính, phương thức của nó), hoặc gọi các hàm của một lớp trong thời điểm chương trình thực thi (runtime).
Tại sao lại cần thiết phải có tính năng này?
Bởi vì đơn giản là có một số chương trình, lúc viết code  chưa xác định được rõ ràng đối tượng nào sẽ được tạo ra mà chỉ đến khi lúc chương trình chạy mới có được đối tượng thực sự, trong trường hợp đó chương trình sẽ phải sử dụng java reflection để biết được rõ hơn về thông tin đối tượng đó.

2. Một số ví dụ đơn giản sử dụng java reflection

Chương trình 1: In ra tất cả các biến và hàm của một lớp
Giả sử chúng ta có một lớp Person như sau:

package test;

public class Person {
 private String name;
 private String dateOfBirth;
 private int weight;
 private int height;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDateOfBirth() {
  return dateOfBirth;
 }

 public void setDateOfBirth(String dateOfBirth) {
  this.dateOfBirth = dateOfBirth;
 }

 public int getWeight() {
  return weight;
 }

 public void setWeight(int weight) {
  this.weight = weight;
 }

 public int getHeight() {
  return height;
 }

 public void setHeight(int height) {
  this.height = height;
 }

}

Đây là chương trình chính sử dụng java reflection:
package test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class JavaReflectionExample {
 public static void main(String[] args) {
  Class personClass = Person.class;
  
  System.out.println("Attributes: ");
  Field[] fields = personClass.getDeclaredFields();
  for(Field field : fields){
   System.out.println(field.getName());
  }
  
  System.out.println("\nMethods: ");
  Method[] methods = personClass.getDeclaredMethods();
  
  for(Method method : methods){
   System.out.println(method.getName());
  }
 }
}

Và kết quả:
Attributes:
name
dateOfBirth
weight
height

Methods:
getName
setName
getDateOfBirth
setDateOfBirth
getWeight
setWeight
getHeight
setHeight

Ngoài khả năng cho phép biết được thông tin của một lớp, sử dụng reflection chúng ta còn có thể gọi một hàm của một lớp ở thời điểm thực thi chương trình
Chương trình 2: Gọi hàm của một lớp
Chương trình này sẽ sử dụng java reflection để gọi hàm tên là add để thực hiện phép cộng "2 + 3".

package test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class JavaReflectionExample1 {
 public int add(int num0, int num1){
  return num0 + num1;
 }
 
 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
  Class javaReflectionExample1Class = JavaReflectionExample1.class;
  Class[] methodParameterTypes = new Class[2];
  methodParameterTypes[0] = Integer.TYPE; // for num0 parameter
  methodParameterTypes[1] = Integer.TYPE; // for num1 parameter
  
  Method addMethod = javaReflectionExample1Class.getMethod("add", methodParameterTypes);
  
  JavaReflectionExample1 javaReflectionExample1 = new JavaReflectionExample1();
  
  Object retObj = addMethod.invoke(javaReflectionExample1, Integer.valueOf(2), Integer.valueOf(3));
  Integer retInt = (Integer)retObj;
  
  System.out.println("2 + 3 = " + retInt);
  
 }
}

Kết quả:
2 + 3 = 5

Viết chương trình tự động đăng nhập facebook bằng Selenium


Hi mọi người, chắc tiêu đề đã nói lên tất cả những điều mình định viết trong bài này :).

Trước khi đi vào việc viết code bằng selenium, chúng ta sẽ dành một vài phần để phân tích về giao diện, các thành phần và cách xác định các thuộc tính của từng thành phần.

1. Phân tích giao diện đăng nhập facebook

Trong trang đăng nhập của facebook, dễ dàng nhận ra là sẽ có 3 thành phần quan trọng:
- 2 textbox dành cho tên người dùng và mật khẩu
- 1 button đăng nhập
Ảnh đăng nhập facebook

2. Sử dụng tính năng Inspect element để xác định các thuộc tính của các textbox

Để có thể điền thông tin tên người dùng(user name) và mật khẩu(password) vào các textbox, chúng ta phải tìm được cách định vị được các textbox đó trong trang web. Bởi vì trong một trang web có thể có rất nhiều các phần tử khác nhau, vậy làm cách nào để ta tìm được chính xác textbox cho tên và mật khẩu trong vô vàn phần tử của trang web? Câu trả lời thật đơn giản, đó làm tìm ra một thuộc tính đặc trưng của textbox tên người sử dụng và mật khẩu. Để làm được điều đó chúng ta sử dụng tính năng "Inspect element" của các trình duyệt, ở đây mình sẽ sử dụng trình duyệt Chrome. Các bước thực hiện:
Bước 1: Đăng nhập vào facebook
Bước 2: Trong trang web facebook, click phải chuột, sẽ hiển thị ra một menu, click chọn "Inspect element" hoặc tổ hợp phím tắt Ctr + Shift + J.
Menu inspect element

Bước 3: Sau khi làm xong bước 2, bạn sẽ thấy một cửa sổ nhỏ bật lên(mình đánh dấu cửa số đó là * nhé, để tiện ), Click vào icon  và sau đó di chuyển đến textbox tên người dùng và textbox mật khẩu.  Sau khi nhấn vào textbox, cửa sổ (*) sẽ hiện thị đoạn code html tương ứng cho textbox
- Textbox tên người sử dụng:


- Textbox mật khẩu:
<input class="inputtext" data-testid="royal_pass" id="pass" name="pass" tabindex="2" type="password" />


Dựa vào đoạn code html của các textbox trên, ta có thể thấy là chúng ta có thể dựa vào thuộc tính id="email" để tìm textbox tên người sử dụng, còn id="password" để tìm textbox mật khẩu.

3.Viết chương trình tự động đăng nhập facebook

3.1 Giới thiệu về selenium

Giờ mới là lúc câu chuyện thực sự bắt đầu :D Giới thiệu vắt tắt một chút về selenium để cho những ai chưa biết dễ dàng lĩnh hội :D
Trang chủ: http://www.seleniumhq.org 
Selenium là một framework dùng để tự động hóa các công việc trên trang web, nghĩa là nếu bình thường chúng ta phải dùng tay click button, nhập thông tin cũng bằng tay :D thì băng việc sử dụng framework này đúng cách(nhớ là đúng cách nhé) chúng ta sẽ viết được những chương trình mà tự động làm việc đó cho chúng ta :).
Selenium thường được sử dụng nhiều trong việc test các phần mềm :)

3.2 Chương trình

Bạn tạo ra một project java, sau đó add thư viện selenium vào, và viết đoạn code như sau:
package test;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class AutoFacebookLogin {
 public static void main(String[] args) {
  WebDriver webDriver = new FirefoxDriver();
  webDriver.get("http://www.facebook.com");
  
  WebElement emailTxt = webDriver.findElement(By.id("email"));
  WebElement passTxt = webDriver.findElement(By.id("pass"));
  
  if(emailTxt!= null && passTxt != null){
   emailTxt.sendKeys("email");
   passTxt.sendKeys("password");
   
   emailTxt.submit();
  }
 }
}
Giải thích:
- Dòng 10: Tạo ra WebDriver. Có rất nhiều loại web driver như ChromeDriver, InternetExplorerDriver, FirefoxDriver,... Trong ví dụ chúng ta sử dụng FirefoxDrive. Đối với các Driver khác, đôi khi chúng ta phải tải thêm một file thực thi dành riêng cho từng loại driver, rồi sau đó gán đường dẫn của file thực thi(Chrome: https://sites.google.com/a/chromium.org/chromedriver/downloads)  đó cho các biến "webdriver.chrome.driver" (Trường hợp Chrome) hoặc "webdriver.ie.driver"(Trường hợp IE). Ví dụ trong trường hợp tạo ChromeDriver:
- Dòng 11: Mở trang facebook
- Dòng 13,14: Tìm kiếm textbox email password bằng id tương ứng của chúng
- Dòng 16: Kiểm tra xem quá trình tìm kiếm các textbox có thành công hay không trước khi làm tiếp những bước tiếp theo
- Dòng 17,18: Nhập email password vào các textbox tương ứng.
- Dòng 20: Tiến hành submit form, tương ứng với việc ta nhấn vào nút Đăng nhập

Source code:
Đang cập nhật

Cảm ơn các bạn vì đã đọc bài của mình

Wednesday 7 October 2015

Giải thuật k láng giềng gần - kNN(k-Nearest Neighbors)


1. Giới thiệu về thuật toán kNN

Bài toán phân loại dữ liệu là một trong những bài toán thường gặp trong cuộc sống và kĩ thuật. có rất nhiều cách tiếp cận và giải thuật được đưa ra để giải quyết bài toán phân loại. Một trong số đó là thuật toán láng giềng gần kNN(k-Nearest Neighbors)

2. Đầu vào và đầu ra

Thuật toán có 2 đầu vào, một là tập các dữ liệu đã biết trước kiểu(loại) của từng dữ liệu(hay còn gọi là tập huấn luyện - training set), đầu vào thứ 2 là dữ liệu, chúng ta chưa biết kiểu(loại) dữ liệu đó. Đầu ra của thuật toán kNN là kiểu dữ liệu của đầu vào thứ 2.

3. Ví dụ áp dụng trong thực tế

Sau đây là một số ví dụ mẫu minh họa cách áp dụng thuật toán kNN trong thực tế.

Ví dụ 1:  giả sử bạn là một quản trị viên của một trang web, công việc hằng ngày của bạn là phân loại phim theo các thể loại(hài, hành động, tình cảm,...), vấn đề sẽ dễ dàng nếu số lượng phim của bạn là nhỏ, bạn có thể tự coi và dựa vào cảm nhận, quyết định xem phim đó thuộc thể loại nào :). Tuy nhiên vấn đề sẽ trở nên phức tạp, khi số lượng phim rất lớn, thì việc coi từng phim và cảm nhận là điều không tưởng, quá thiếu hiệu quả, lúc đó bạn sẽ bắt đầu nghĩ ngay tới việc sử dụng phần mềm giúp bạn tự động phân loại phim. Nói cách khác, việc phân loại phim chính là bài toán phân loại dữ liệu, và chúng ta có thể sử dụng thuật toán kNN trong trường hợp này.

Ví dụ 2: Bạn được yêu cầu viết một phần mềm, nhận vào một tệp ảnh và đưa ra kết quả đó là tệp ảnh đó miêu tả con số nào từ 0 đến 9. Việc chúng ta làm ở đây phát biểu theo một cách khác đó là xác định xem tệp ảnh đầu vào nằm ở trong kiểu nào? kiểu số 0 hay kiểu số 1 hay kiểu số 2,... hay kiểu số 9.

4. Tư tưởng và cách thức làm việc của giải thuật kNN

Bây giờ chúng ta sẽ đi vào chi tiết cách thức hoạt động của giải thuật kNN. Đầu tiên chúng ta phải chuẩn bị một tập huấn luyện(training set) mà tất cả các dữ liệu trong tập đó đều biết trước được thuộc loại nào. Người dùng sẽ đưa vào một dữ liệu chưa biết được thuộc loại nào. kNN sẽ so sánh dữ liệu đó với tất cả dữ liệu trọng tập huấn luyện và chọn ra k dữ liệu gần giống nhất. Trong k dữ liệu đó, kNN sẽ xem xét xem loại nào là loại chiếm đa số --> và sẽ đưa ra kết luận rằng tập dữ liệu cần xác định thuộc loại đó. Có vẻ cũng hơi khó hiểu nhỉ? Bây giờ chúng ta sẽ đi vào chi tiết một ví dụ, hi vọng là các bạn sau khi xem xong ví dụ, sẽ hiểu rõ hơn :)

Ví dụ này mình lấy trong cuốn "Machine learning in action" của Petter Harington.

Chúng ta sẽ đi phân loại xem một bộ phim thuộc thể loại phim hành động hay phim tình cảm. Việc phân loại phim sẽ được xác định bằng cách đếm số lượng cú đá hoặc số lượng nụ hôn trong phim. Ở đây, chúng ta đã một tập huấn luyện(training set), tập đó chứa một số phim đã biết số lượng cú đá, nụ hôn trong phim đó, và loại phim được cho trong bảng sau:

Tên phim
Số lượng cú đá
Số lượng nụ hôn
Loại phim
California Man
3
104
Tình cảm
He isn't really into dudes
2
100
Tình cảm
Beautiful Woman
1
81
Tình cảm
Kevin Longblade
101
10
Hành động
Robo Slayer 3000
99
5
Hành động
Amped II
98
2
Hành động
?
18
90
Chưa xác định

Chúng ta đã biết được số lượng cú đá, số lượng nụ hôn trong phim. Nhiệm vụ của chúng ta ở đây là xác định xem phim ? thuộc thể loại nào?

Đầu tiên chúng ta sẽ xác định xem sự giống nhau của phim ? với các phim khác như thế nào
Để làm được điều đó, chúng ta sẽ sử dụng euclidean distance.

Euclidean distance là việc chúng ta tìm khoảng cách giữa hai điểm trong không gian, ví dụ cho 2 điểm ${P_1(x_1, y_1)}$ và ${P_2(x_2, y_2)}$ thì Euclidean distance sẽ được tính theo công thức:
$$d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$$

Để áp dụng trong euclidean distance vào trong trường hợp này, chúng ta sẽ coi mỗi phim sẽ được biểu diễn bởi một điểm trong tọa độ Oxy với số lượng cú đá là tọa độ x và số lượng nụ hôn là tọa độ y. Điều đó có nghĩa là phim California Man sẽ được biểu diễn bởi điểm (3, 104); phim He isn't really into dudes sẽ được biểu diễn bởi điểm (2, 100), ..

Gọi d là euclidean distance

Thì:
  • California Man:
$$d = \sqrt{(18-3)^2 + (90-104)^2} = 20.5$$   
  • He isn’t really into dudes:
$$d = \sqrt{(18-2)^2 + (90-100)^2} = 18.7$$ 
  • Beautiful Woman:
$$d = \sqrt{(18-1)^2 + (90-81)^2} = 19.2$$ 
  • Kevin Longblade:
$$d = \sqrt{(18-101)^2 + (90-10)^2} = 115.3$$ 
  • Robo Slayer 3000:
$$d = \sqrt{(18-99)^2 + (90-5)^2} = 117.4$$ 
  • Amped II:
$$d = \sqrt{(18-98)^2 + (90-2)^2} = 118.9$$ 

Sau khi tính toán, chúng ta sẽ được bảng sau:


Tên phim
Euclidean distance
California Man
20.5
He isn’t really into dudes
18.7
Beautiful Woman
19.2
Kevin Longblade
115.3
Robo Slayer 3000
117.4
Amped II
118.9


Chúng ta đã có khoảng cách euclidean từ phim chưa biết loại tới từng phim trong tập huấn luyện, giờ chúng ta sẽ tìm ra k làng giềng gần nhất bằng cách sắp xếp các phim theo thứ tự euclidean distance từ nhỏ đến lớn. Giả sử k = 3 thì 3 làng giềng gần nhất, đó là các phim California Man, He isn't really into dudes và Beautiful Woman. thuật toán kNN sẽ lấy loại phim nào chiếm ưu thế trong các láng giếng gần nhất để làm loại phim cho phim cần được xác định loại. Vì 3 phim trên đều là thể loại Tình cảm ==> Phim cần xác định thuộc thể loại phim tình cảm.

5. Nhược điểm của giải thuật kNN

giải thuật kNN thích hợp cho việc phân loại dữ liệu chứ giải thuật này không có khả năng phân tích dữ liệu để tìm ra các thông tin có giá trị. Trong quá trình kNN hoạt động, nó phải tính toán "khoảng cách" từ dữ liệu cần xác định loại đến tất cả các dữ liệu trong tập huấn luyện (training set) ==> nếu tập huấn luyện quá lớn, điều đó sẽ làm cho thời gian chạy của chương trình sẽ rất lâu.