Posted in Spark

Một số kinh nghiệm làm spark streaming

  • Xóa checkpoints khi run lại job , bởi nếu không sẽ thường bị lỗi KafkaError , nếu trong job đó có Accumulator thì sẽ bị lỗi cast từ Interger sang Long
  • Cố gắng ít stages nhất có thể . Nếu map 1 lần kafka mà k persist hay cache lại sẽ load lại đúng offset đó trong kafka . Sẽ lâu
  • Lưu lại checkpoints nếu job sparkstreaming chết …. initRdd
  • Updating
  • TreeSet…mất bản ghi …
  • Thiết kế key value sao cho ít stages nhất ….
  • ByteArray for key
  • put accumulator to mapPartitions or UPdateStateBykey . Set accumulator về 0 nếu k , giá trị sẽ bị cache lại
  • Check WebUI
  • In ra Accumulator
  • Queue streaming –> tăng batch duration
Advertisements
Posted in Khác

Design Pattern – Singleton Pattern

Gần đây , khi làm 1 job spark streaming . Mình được yêu cầu làm 1 job liên quan tới spark rồi tính toán lại 1 kết quả phần trăm công việc đó và hiển thị visualize lại cái phần trăm đó được theo mốc thời gian để có thể xem khi nào phần trăm đó đi lên hay đi xuống . Thường thì mọi người đã từng làm job này sẽ đẩy cái phần trăm này lên elasticsearch rồi dùng grafana để load cái phần trăm này lên và hiển thị .

 

maxresdefault

Một trong những vấn đề mình gặp phải , đó chính là mỗi batch streaming thì thường là vài giây là sẽ load data lại một lần . Với mỗi batch như thế , nếu mỗi lần đẩy dữ liệu vào elastic mà phải tạo một kết nối mới tới Elastic thì sẽ khá tốn thời gian và tài nguyên và cảm giác hơi ngu ngu . Quá nhiều connections cũng không phải hay ho gì .

Từ đó mình thấy có thể dùng Singeleton Pattern

1.Giới thiệu

Mọi người có thể đọc qua về singeleton ở trang này : http://code5s.com/ngon-ngu-lap-trinh/java/design-pattern-singleton.html

2. Code

Khởi tạo 1 class ESMoritoringService

public class ESMonitoringService {

    private static ESMonitoringService esMonitoringService;
// để hàm khởi tạo private để chỉ class này có thể khởi tạo 
chính nó 
    private ESMonitoringService(){
        // khoi tao
    }
//vì có thế có nhiều threads cùng gọi tới method getInstance để sử dụng 
object ESMonitoringService nên dùng từ khóa synchronized
    public static ESMonitoringService getInstance(){
        synchronized (esMonitoringService){
            if (esMonitoringService==null){
                // create instance
                esMonitoringService= new ESMonitoringService();
            }
            return esMonitoringService;
        }
    }
}

Khi đó trong job spark streaming , khi muốn đẩy dữ liệu vào elastic ta có thể :

ESMonitoringService esMonitoringService= ESMonitoringService.getInstance();
và gọi các method trong ESMonitoringService để index document vào elastic
Posted in Khác

SPARK

1.Khởi tạo Spark trong Java

import org.apache.spark.SparkConf;

import org.apache.spark.api.java.JavaSparkContext;

 

SparkConf conf = new SparkConf().setMaster(“local”).setAppName(“Filtering”);

JavaSparkContext sc = new JavaSparkContext(conf);

Hai tham số của SparkConf đó là :

  • Cluster URL , local có nghĩa là Spark sẽ chạy 1 thread trong máy local , không kết nối với các cluster khác
  • Tên của application , Nó sẽ xác định tên của applicating của bạn trong cluster manager’s UI nếu bạn kết nối tới một clusster
  • Và một số các tham số khác để configuring ứng dụng của bạn sẽ hoạt động ntn ….

Để shut down Spark , có thể gọi stop() method , hoặc thoát application như : System.exit(0) hoặc sys.exit()

2.Programming with RDDs

Spark’s core abstraction for working with data , the resilient distributed dataset(RDD). RDD là tập hợp rời rạc của các elements . Spark tự động phân tán dữ liệu trong RDDs trong các cluster và song song thực hiện chúng

Mỗi RDD trong Spark đơn giản là một tập phân phối bất biến của các objects . Mỗi RDD được chia ra thành các partitions , có thể được tính toán ở các nodes khác nhau của các cluster . RDD có thể chưas tất các các type Python , Java , Scala object , kể cả user-defined classes .

Users create RDDs in two ways : by loading an external dataset , or distributing a collection of objects ( list or set ) in their driver program .Sau khi khởi tạo , RDDs cung cấp 2 dạng operations : transformations actions . Transformations xây dựng RDD mới từ precious one . Ví dụ , tạo RDD mới mà chỉ bao gồm các string mà bao gôm từ Python . Actions thì tính toán kết quả dựa vào một RDD , và trả về kết quả cho driver program hoặc lưu nó vào external storage system ( như HDFS) . Ví dụ first() sẽ trả về elements đầu tiên của một RDD.

Transformations và actions khác nhau theo cách mà Spark xử lý RDDs đó . Chúng ta có thể định nghĩa RDDs mới bất kì lúc nào , nhưng Spark chỉ tính toán nó theo a lazy fashion , đó là thực hiện khi RDDs này trong action đầu tiên . Điều này có thể là khó hiểu , nhưng lại hợp lý khi bạn làm việc với Big Data . Ví dụ , trong phương thức first() , Spark sẽ scan file để tìm ra first matching line ; nó sẽ không đọc hết cả file .

Sparks’s RDDs mặc định tính toán lại mỗi lần bạn chạy một action trong nó . Nếu bạn muốn dùng một RDD trong nhiều actions , bạn có thể yêu cầu Spark persit , sử dụng RDD.persit(). Điều này là hợp lý bởi vì , nếu bạn không sử dụng lại RDD , chả có lý do gì để tốn bộ nhớ để lưu.

CREATING RDDs

Users create RDDs in two ways : by loading an external dataset , or distributing a collection of objects ( list or set ) in their driver program .Cách đơn giản nhất để tạo ra RDDs là sử dụng một collection có sẵn và pass it to SparkContext’s parallelize() method (đòi hỏi bạn phải có dataset trong memory ở một machine )

JavaRDD<String> lines = sc.parallelize(Arrays.asList(“pandas”,”i like pandas”));

Một cách phổ biến khác để tạo ra RDDs đó là load data from external storage . Chúng ta có thể load rất nhiều các định dạng file khác nhau như text,json , csv,…Với file text :

JavaRDD<String> lines = sc.textFile(“README.txt”);

RDD Operations

RDDs hỗ trợ 2 kiểu operations : transformations actions . Transformations là một operations trong RDDs mà sẽ trả lại một RDD mới , như map() hay filter() . Actions là một operations mà sẽ trả về kết quả cho driver program hoặc write it to storage và tính toán như count() first()

Transformations

Giả dụng chúng ta có một logfile , log.txt , có một số các messages , chúng ta muốn chọn ra các error message . Chúng ta có thể sử dụng filter() transformation :

JavaRDD<String> inputRDD = sc.textFile(“README.txt”);

JavaRDD<String> errorsRDD = inputRDD.filter(

new Function<String,Boolean>(){

public Boolean call(String x){return x.contains(“error”);}

}

);

filter() sẽ không thay đổi inputRDD mà sẽ trỏ đến một RDD hoàn toàn mới . Chúng ta thu được RDDs mới từ các RDD sử dụng transformations . Spark sẽ lưu trữ các phụ thuộc giữa các RDDs khác nhau , được gọi là lineage graph . Nó sẽ được sử dụng để tính toán RDD và recover lost data nếu một phần của persistent RDD bị mất mát :

ACTIONS

Ở ví dụ trước , chúng ta có thể muốn in ra thông tin về errorsRDD . Chúng ta có thể sử dụng các actions như , count() sẽ trả về số lượng , và take() sẽ thu thập một số lượng elements từ RDD

System.out.println(“Input had ” + badLinesRDD.count() + ” concerning lines”)

System.out.println(“Here are 10 examples:”)

for (String line: badLinesRDD.take(10)) {

System.out.println(line);

}

RDD cũng có collect() function trả về toàn bộ RDD (Phải đảm bảo là toàn bộ dataset phải fit in memory on a single machine , không nên sử dụng với datasets quá lớn ). Trong phần lớn RDDs không thể sử dụng collect bởi vì nó quá lớn . Chúng ta sẽ viết data ra các hệ lưu trữ dữ liệu phân tán như là HDFS hoặc AMAZON S3 . Chúng ta có thể lưu contents của một RDD sử dụng saveAsTextFile() action , saveAsSequenceFile() ,

LAZY EVALUATION

Spark sẽ không thực thi cho đến khi nó nhìn thấy một action . Ví dụ nếu ta gọi một transformation ở một RDD ( ví dụ map() ) , operation sẽ không thực thi ngay tức thì . Thay vào đó , Spark internally records metadata để chỉ ra rằng operation này đã được yêu cầu . Thay vì nghĩ RDD chứa dữ liệu cụ thể , chúng ta có thể nghĩ rằng mỗi RDD sẽ bao chứa các chỉ dẫn rằng các data sẽ được xử lý như thế nào . Trong một hệ thống như Hadoop MapReduce , các lập trình viên thường xuyên dành nhiều thời gian để nghĩ ra cách gộp các operations lại với nhau để minimize the number of MapReduce passes . Trong Spark , không có ích lợi gì nếu việt một single complex map thay vì dàn trải thành nhiều simple operations

Passing Functions to Spark

Trong Java,các functions được quy định như các objects mà implement một trong những Spark’s function interfacces từ org.apache.spark.api.java.function package. Có rất nhiều các interfaces dựa vào kiểu trả về của function .

Function name Method to implement Usage
Function<T,R> R call(T) 1 đàu vào , 1 đầu ra , sử dụng với operations như map() filter()
Function2<T1,T2,R> R call(T1,T2) 2 đầu vào , 1 đầu ra , sử dụng với operations như aggregate() fold()
FlatMapFunction<T,R> Iterable<R> call(T) 1 đầu vào , không hoặc nhiều outputs , sử dụng với operations như flatMap()

 

Java function passing with anonymous inner class

 

RDD<String> errors = lines.filter(new Function<String, Boolean>() {

public Boolean call(String x) { return x.contains(“error”); }

});

Java function passing with named class

class ContainsError implements Function() {

public Boolean call(String x) {

return x.contains(“error”); } }

RDD errors = lines.filter(new ContainsError());

Java function class with parameters

class Contains implements Function() {

private String query;

public Contains(String query) { this.query = query; }

public Boolean call(String x) { return x.contains(query); } }

RDD errors = lines.filter(new Contains(“error”));

Trong Java 8 , chúng ta có thể sử dụng lambda expressions để implement ngắn gọn function interfaces :

Java function passing with lambda expression in Java 8

RDD errors = lines.filter(s -> s.contains(“error”));

Common Transformations and Actions

Element-wise transformations

Hai transformations phổ biến nhất mà thường xuyên sử dụng đó là map() filter() . The map() transformations sẽ cần một function và áp dụng nó vào từng element trong RDD với kết quả của function sẽ trở thành giá trị mới của từng element trong RDD kết quả . The filter() transformation sẽ cần một function và trả về một RDD mà chỉ chứa các phần từ mà vượt qua được filter() function.

Nên nhớ rằng , map()’s sẽ trả về kiểu có thể không giống như input type . Ví dụ về một map() mà bình phương các số trong một RDD

Java squaring the values in an RDD

JavaRDD rdd = sc.parallelize(Arrays.asList(1, 2, 3, 4));

JavaRDD result = rdd.map(new Function() {

public Integer call(Integer x) { return x*x; }

});

System.out.println(StringUtils.join(result.collect(), “,”));

Đôi khi chúng ta muốn sinh ra multiple output elements từ mỗi input element . Operation này tên là flatMap() . Như với map() , function flatMap() sẽ được gọi riêng biệt cho từng element của input RDD . Nhưng thay vì chỉ trả về một element , chúng ta trả về một iterator với giá trị trả về . Một flatMap() đơn giản để tách các string thành các word :

flatMap() in Java, splitting lines into multiple words

JavaRDD lines = sc.parallelize(Arrays.asList(“hello world”, “hi”)); JavaRDD words = lines.flatMap(new FlatMapFunction() {

public Iterable call(String line) {

return Arrays.asList(line.split(” “));

}

});

words.first(); // returns “hello”

Pseudo set operations

RDDs hỗ trợ rất nhiều các operations toán , như union intersection . Các operations này đòi hỏi các RDD cùng loại

Tập các elements của chúng ta có thể có trùng lặp , nếu muốn lấy các phần tử riêng biệt , chúng ta có thể sử dụng RDD.distinct() transformation . distinct() khá tốn kém , vì nó phải load tất cả các data .

Toán tử đơn giản nhất là union(other), nó sẽ trả về RDD bao hồm data tử cả 2 RDD input . Spark’s union() có thể chứa dữ liệu trùng lặp

Toán tử intersection(other)  trả về phần tử mà nằm ở cả hai RDD , intersection() thì loại bỏ trùng lặp .

Toán tử subtract(other) sẽ trả về RDD mà năm trong RDD đầu tiên và không nằm trong RDD thứ hai

Toán tử cartesian(other) transformation trả về kết quả tất cả các cặp (a,b) với a năm trong source RDD và b trong RDD còn lại .

ACTIONS

Action phổ biến nhất là reduce() , nó sẽ takes a function triển trên 2 element của RDD của bạn và trả về một element mới cùng kiểu .

reduce() in Java

Integer sum = rdd.reduce(new Function2() {

public Integer call(Integer x, Integer y) { return x + y; }

});

fold() aggregate() …………

Operation đơn giản và phổ biến nhất để trả về dữ liệu cho driver program đó chính là collect() . collect() thường được sử dụng trong unit tests khi mà toàn bộ contents của RDD có thể fit in memory .

take(n) trả về n phần tử từ RDD và cố gắng tối thiểu số partitions mà nó truy cập . Nếu mà tồn tại thứ tự trong data của chúng ta , chúng ta có thể lấy về top elements từ một RDD sử dụng top() . top() sẽ sử dụng sắp xếp mặc định trong data của chúng ta , nhưng chúng ta có thể sử dụng hàm so sánh của chúng ta để lấy về top elements .

Đôi khi chúng ta cần lấy mẫu trong dữ liệu chúng ta . The takeSample(withReplecement, num, seed) function cho phép chúng ta lấy mẫu trong dữ liệu của chúng ta with or without replacement

Actions foreach() sẽ cho chúng ta tính toán trên từng element trong RDD

Converting Between RDD Types

Một số functions chỉ thích hợp cho một vài kiểu RDDs , như mean() variance() trên numeric RDDs hoặc join() trên key/value pair RDDs .

Thông thường , có một vài classes đặc biẹt tên là JavaDoubleRDD JavaPairRDD với một vài phương thức thêm vào cho những kiểu dữ liệu data này .

Creating DoubleRDD in Java

JavaDoubleRDD result = rdd.mapToDouble(

new DoubleFunction() {

public double call(Integer x) {

return (double) x * x;

}

});

System.out.println(result.mean());

Persistence (Caching)

Đôi khi chúng ta muốn sử dụng một RDD nhiều lần . Nếu chúng ta ngây thơ , thì Spark sẽ tính toàn lại RDD vào mỗi lần chúng ta gọi một action trên RDD . Để loại trừ tính toán RDD rất nhiều lần , chúng ta có thể yêu cầu Spark persist data . Khi chúng ta yêu cầu Spark persist một RDD , nodes mà tính toán RDD sẽ lưu lại partitions của nó . Nếu một node chứa data persisted mà fails , Spark sẽ tính toán lại lost partitions của data khi cần thiết . Spark có rất nhiều cấp độ persistence để chọn dựa vào mục đích cũng chúng ta , persist() mặc định sẽ lưu trữ dữ liệu trong JVM heap như một unserialized objects . Khi chúng ta viết dữ liệu ra disk hay off-heap storage , dữ liệu luôn luôn được serizlized .

Nếu bạn thử cache quá nhiều dữ liệu fit in memory . Spark sẽ tự động thu hồi old partitions sử dụng Least Recently Used(LRU) cache policy.Với memory-only storage levels , nó sẽ tính toán lại các partitions vào lần kết tiếp access , còn với memory-and-disk , nó sẽ ghi ra disk . Hay có nghĩa là , bạn sẽ không phải quá lo lắng khi yêu cầu Spark to cache quá nhiều data . Nhưng cũng k nên caching unnecessary data dẫn đến phải tính toán lại useful data và thêm thời gian tính toán lại

Cuối cùng , RDDs cung cấp một method tên là unpersist() cho phép remove các RDDs từ cache

3.Working with Key/Value Pairs

Spark cung cấp một operations đặc biệt bao gồm key/value pairs . Những RDDs này được gọi là pair RDDs . Pair RDDs cho phép chúng ta act on each key song song hoặc regroup dữ liệu thông qua mạng . Ví dụ , pair RDDs có một phương thức reduceByKey() có thể tổng hợp data riêng cho từng key , và một phương thức join() có thể gộp 2 RDDs lại với nhau bằng cách nhóm các elements với cùng key .

Creating Pair RDDs

Có một số cách để get pair trong Spark . Rất nhiều cách đọc file mà trả về pair RDDs . Trong trường hợp chúng ta có một RDD thông thường mà chúng ta muốn biến đổi thành pair RDD . Chúng ta có thể chạy map() function .

 

 

 

 

Creating a pair RDD using the first word as the key in Java

PairFunction keyData =

new PairFunction() {

public Tuple2 call(String x) {

return new Tuple2(x.split(” “)[0], x);

}

};

JavaPairRDD pairs = lines.mapToPair(keyData);

Để tạo ra pair RDD từ in-memory collection trong Java , chúng ta sử dụng SparkContext.parallelizePairs()

Transformations on Pair RDDs

Pair RDDs cho phép sử dụng tất các các transformations của một RDDs thông thường . Pair RDDs gồm các tuples , chúng ta cần pass functions mà operate on tuples hơn là các phần tử riêng biệt .

Aggregations

Khi datasets được mô tả theo key/value pairs , là điều bình thường nếu muốn aggregate statistics acroos tất cả các elements với cùng key .

reduceByKey() khá là giống với reduce(); cả hai đều take a function và sử dụng để gộp các values . reduceByKey() chạy song song các reduce operations , mỗi operations cho một key trong dataset

foldByKey()cũng khá là tương tự fold(), both use a zero value ò the same type of the data in our RDD and combination function . As with fold() , the provided zẻo value for foldByKey() should have no impact ưhen added ưith your combination function to another element.

Gọi reduceByKey() foldByKey() sẽ tự động thực thi kết hợp locally trên mỗi máy trước khi tính toán global cho từng key . combineByKey() interface sẽ cho phép bạn customize combining behavior

Word count in Java

JavaRDD input = sc.textFile(“s3://…”)

JavaRDD words = rdd.flatMap(new FlatMapFunction() {

public Iterable call(String x) { return Arrays.asList(x.split(” “)); }

});

JavaPairRDD result = words.mapToPair(

new PairFunction() { public Tuple2 call(String x) { return new Tuple2(x, 1); }

}).reduceByKey(

new Function2() {

public Integer call(Integer a, Integer b) { return a + b; }

});

Chúng ta sẽ thực thi word count nhanh hơn sử dụng countByValue() function ở RDD đầu tiên :

input.flatMap(x => x.split(” “)).countByValue()

combineByKey() is the mose general of the per-key aggregation functions . Các combiners per-key khác thường implemented nó . Như aggregate() , combineByKey() cho phép người dùng trả về giá trị không cùng kiểu với input data .

combineByKey() sẽ đi qua các elements trong các partition , mỗi element sẽ có một key mà lần đầu xuất hiện hoặc

 

Posted in Khác

Introduction to Latent Dirichlet Allocation

Latent Dirichlet Allocation – Blei & Ang & Jordan , JMLR 2003

Introduction

Giả sử bạn có một tập các câu sau đây :

  • I like to eat broccoli and bananas.
  • I ate a banana and spinach smoothie for breakfast.
  • Chinchillas and kittens are cute.
  • My sister adopted a kitten yesterday.
  • Look at this cute hamster munching on a piece of broccoli.

Thế thì LDA là gì ? Đó là một cách từ động khám phá ra các topics mà các câu trên chứa. Ví du, cho các câu trên và yêu cầu cho 2 topics, LDA có thể sinh ra một kết quả như kiểu này :

  • Sentences 1 and 2: 100% Topic A
  • Sentences 3 and 4: 100% Topic B
  • Sentence 5: 60% Topic A, 40% Topic B
  • Topic A: 30% broccoli, 15% bananas, 10% breakfast, 10% munching, … ( tại điểm này , bạn có thể diễn tả topic A là về food)
  • Topic B: 20% chinchillas, 20% kittens, 20% cute, 15% hamster, … (tại điểm này , bạn có thể diễn tả topic B là về cute animals)

Làm thế nào để LDA có thể thực hiện được điều này ?

LDA Model

Chi tiết hơn , LDA miêu tả các văn bản như là sự pha trộn của các topics that spit out words với các xác suất nhất định . Nó giả sử các văn bản được tạo ra theo cách sau : khi bạn viết mỗi văn bản , bạn

  • Quyết định số lượng từ N mà document sẽ có ( theo một phân phối Poisson )
  • Chọn một chủ đề hỗn hợp cho document này (theo một phân phối Dirichlet trên một tập hợp cố định K chủ đề). Ví dụ , giả sử bạn có hai topics bên trên : food và cute animal , bạn có thể chọn rằng document này sẽ bao gồm 1/3 food và 2/3 cute animals.
  • Generate each word w_i trong document này bằng cách:
    • Đầu tiên là chọn một topic (theo phân phối đa thức mà bạn đã láy ví dụ bên trên , ví dụ , bạn có thể chọn food topic với xác suất 1/3 và cute animals topic với xác suất 2/3).
    • Sử dụng topic để sinh ra các từ (theo phân phối của topic’s multinomial). Ví dụ , nếu bạn chon food topic , bạn có thể sinh ra được các từ “broccoli” với xác suất 30% , “bananas” với xác suất 15% , và cứ thế …

Giả sử this generative model này cho một tập hợp các documents , LDA sau đó cố gắng để quay lui (backtrack) từ các tài liệu để tìm thấy một tập hợp các chủ đề mà rất có thể đã tạo ra collection .

Example

Ví dụ . Tuân theo quy trình bên trên , khi sinh ra một số document D cụt hể , bạn có thể :

  • Chọn 5 là số lượng từ trong D.
  • Quyết định rằng D sẽ là 1/2 về food và  1/2 về cute animals.
  • Chọn từ đầu tiên trong food topic , và bạn sẽ có từ “broccoli”.
  • Chọn từ thứ hai tới từ cute animals topic, bạn sẽ có “panda”.
  • Chọn từ thứ 3 tới từ cute animals topic , sẽ cho bạn từ “adorable”.
  • Chọn từ thứ tư tới từ food topic, sẽ cho bạn từ “cherries”.
  • Chọn từ thứ năm tới từ food topic, sẽ cho bạn từ “eating”.

Như thế document được sinh ra từ LDA sẽ là  “broccoli panda adorable cherries eating” (ghi nhớ rằng LDA là a bag-of-words model).

Learning

Giả sử bạn đã có tập các documents. You’ve chosen some fixed number of K topics to discover, and want to use LDA to learn the topic representation of each document and the words associated to each topic. How do you do this? One way (known as collapsed Gibbs sampling) is the following:

  • Go through each document, and randomly assign each word in the document to one of the K topics.
  • Notice that this random assignment already gives you both topic representations of all the documents and word distributions of all the topics (albeit not very good ones).
  • So to improve on them, for each document d…
    • Go through each word w in d…
      • And for each topic t, compute two things: 1) p(topic t | document d) = the proportion of words in document d that are currently assigned to topic t, and 2) p(word w | topic t) = the proportion of assignments to topic t over all documents that come from this word w. Reassign w a new topic, where we choose topic t with probability p(topic t | document d) * p(word w | topic t) (according to our generative model, this is essentially the probability that topic t generated word w, so it makes sense that we resample the current word’s topic with this probability). (Also, I’m glossing over a couple of things here, in particular the use of priors/pseudocounts in these probabilities.)
      • In other words, in this step, we’re assuming that all topic assignments except for the current word in question are correct, and then updating the assignment of the current word using our model of how documents are generated.
  • After repeating the previous step a large number of times, you’ll eventually reach a roughly steady state where your assignments are pretty good. So use these assignments to estimate the topic mixtures of each document (by counting the proportion of words assigned to each topic within that document) and the words associated to each topic (by counting the proportion of words assigned to each topic overall).

Layman’s Explanation

In case the discussion above was a little eye-glazing, here’s another way to look at LDA in a different domain.

Suppose you’ve just moved to a new city. You’re a hipster and an anime fan, so you want to know where the other hipsters and anime geeks tend to hang out. Of course, as a hipster, you know you can’t just ask, so what do you do?

Here’s the scenario: you scope out a bunch of different establishments (documents) across town, making note of the people (words) hanging out in each of them (e.g., Alice hangs out at the mall and at the park, Bob hangs out at the movie theater and the park, and so on). Crucially, you don’t know the typical interest groups (topics) of each establishment, nor do you know the different interests of each person.

So you pick some number K of categories to learn (i.e., you want to learn the K most important kinds of categories people fall into), and start by making a guess as to why you see people where you do. For example, you initially guess that Alice is at the mall because people with interests in X like to hang out there; when you see her at the park, you guess it’s because her friends with interests in Y like to hang out there; when you see Bob at the movie theater, you randomly guess it’s because the Z people in this city really like to watch movies; and so on.

Of course, your random guesses are very likely to be incorrect (they’re random guesses, after all!), so you want to improve on them. One way of doing so is to:

  • Pick a place and a person (e.g., Alice at the mall).
  • Why is Alice likely to be at the mall? Probably because other people at the mall with the same interests sent her a message telling her to come.
  • In other words, the more people with interests in X there are at the mall and the stronger Alice is associated with interest X (at all the other places she goes to), the more likely it is that Alice is at the mall because of interest X.
  • So make a new guess as to why Alice is at the mall, choosing an interest with some probability according to how likely you think it is.

Go through each place and person over and over again. Your guesses keep getting better and better (after all, if you notice that lots of geeks hang out at the bookstore, and you suspect that Alice is pretty geeky herself, then it’s a good bet that Alice is at the bookstore because her geek friends told her to go there; and now that you have a better idea of why Alice is probably at the bookstore, you can use this knowledge in turn to improve your guesses as to why everyone else is where they are), and eventually you can stop updating. Then take a snapshot (or multiple snapshots) of your guesses, and use it to get all the information you want:

  • For each category, you can count the people assigned to that category to figure out what people have this particular interest. By looking at the people themselves, you can interpret the category as well (e.g., if category X contains lots of tall people wearing jerseys and carrying around basketballs, you might interpret X as the “basketball players” group).
  • For each place P and interest category C, you can compute the proportions of people at P because of C (under the current set of assignments), and these give you a representation of P. For example, you might learn that the people who hang out at Barnes & Noble consist of 10% hipsters, 50% anime fans, 10% jocks, and 30% college students.

Real-World Example

Finally, I applied LDA to a set of Sarah Palin’s emails a little while ago (see here for the blog post, hoặc đây là một ứng dụng cho phép bạn duyệt qua các emails bằng LDA-learned categories), dưới đây là 1 bán tóm gọn . Đây là một vài topics mà thuật toán học được :

  • Trig/Family/Inspiration: family, web, mail, god, son, from, congratulations, children, life, child, down, trig, baby, birth, love, you, syndrome, very, special, bless, old, husband, years, thank, best, …
  • Wildlife/BP Corrosion: game, fish, moose, wildlife, hunting, bears, polar, bear, subsistence, management, area, board, hunt, wolves, control, department, year, use, wolf, habitat, hunters, caribou, program, denby, fishing, …
  • Energy/Fuel/Oil/Mining: energy, fuel, costs, oil, alaskans, prices, cost, nome, now, high, being, home, public, power, mine, crisis, price, resource, need, community, fairbanks, rebate, use, mining, villages, …
  • Gas: gas, oil, pipeline, agia, project, natural, north, producers, companies, tax, company, energy, development, slope, production, resources, line, gasline, transcanada, said, billion, plan, administration, million, industry, …
  • Education/Waste: school, waste, education, students, schools, million, read, email, market, policy, student, year, high, news, states, program, first, report, business, management, bulletin, information, reports, 2008, quarter, …
  • Presidential Campaign/Elections: mail, web, from, thank, you, box, mccain, sarah, very, good, great, john, hope, president, sincerely, wasilla, work, keep, make, add, family, republican, support, doing, p.o, …

Đây là một ví dụ một email rời vào Trig/Family/Inspiration category (particularly representative words are highlighted in blue):

Trig Email

Đây là một trích đoạn từ một email mà sẽ 10% rời vào Presidential Campaign/Election category (màu đỏ ) và  90% rơi vào Wildlife/BP Corrosion category (màu xanh):

Wildlife-Presidency Email

Lược dịch từ : https://www.quora.com/What-is-a-good-explanation-of-Latent-Dirichlet-Allocation/answer/Edwin-Chen-1?srid=nqv8

Posted in Khác

Recommender systems

  1. Introduction to Recommender Systems

Recommender Systems (RSs) là một software tools hay một kĩ thuật cung cấp gợi ý cho items tùy mục đích sử dụng của user . Gợi ý cung cấp mục đích để hỗ trợngười dùng trong rất nhiều quá trình quyết định , như là items nào nên mua , bài nhạc nào nên nghe . Phát triển một RSs là một nỗ lực đa ngành trong đó bao gồm các chuyên gia từ nhiều lĩnh vực như Artificial intelligence, Human Computer Interaction, Information Technology, Data Mining, Statistics, Adaptive User Interfaces, Decision Support Systems, Marketing, or Consumer Behavior.

Trong trường hợp của một book RSs , nó sẽ hỗ trợ người dùng chọn sách để đọc . Trong một trang Web rất phổ biến , Amazon.com , trang nay triển khai một RS để cá nhân hoá của hàng online cho từng khách hàng . Hệ thống recommendations thường là được cá nhân hoá , các người dùng hay nhóm người dùng khác nhau thường nhận được các gợi ý khác nhau . Cũng có những hệ thống gợi ý non-personalized . Điển hình là 10 bài hát đang phổ biến nhất hay , 10 quyển sách đang bán chạy nhất . Hệ thống non-personalized có thể hữu dụng trong các trường hợp nhất định , tuy nhiên trong RS research nó không được qua tâm nhiều lắm .

Recommender systems have proven to be valuable means for online users to cope with the information overload and have . Trong những năm gần đây , hệ thống recommender đã được phát triển đáng kể . RSs đóng vai trò quan trọng trong các trang web có xếp hạng cao như Amazonlcom , Youtube , Netflix , Yahoo , Tripadvisor , IMDb . Các công ty media phát triển và triển khai các RSs như một phần của dịch dụ cung cấp cho người dùng , Ví dụ Netflix , hệ thống dịch vụ thuê phim trực tuyến , trao giải thưởng 1 triệu đô cho team đầu tiên mà cải tiến đáng kể so với hệ thống RSs của họ ( 10% với RSME) . Tương ứng , có rất nhiều kĩ thuộc cho recommendation đã được đề xuất trong thập kỉ vừ qua , rất nhiều trong số đó đã thực thi thành công trong môi trường thương mại

  1. Data Mining Methods for Recommender Systems

Real-life data cần được tiền xử lý để làm sao có thể sử dụng các kĩ thuật machine learning để làm tiếp . 3 vấn đề mà đặc biệt quan trọng khi thiết kế một RS . Đầu tiên sẽ là các similarity hoặc distance meansures . Rồi vấn đề lấy mấu dữ liệu để làm giảm số lượng itesm trong tập lớn giữ liệu mà vẫn giữ được đặc điểm chính của nó . Cuối cùng là một số kĩ thuật để reduce dimensionality

  • Similarity Meansures

Một trong những phương pháp ưa thích để collaborative filtering recommenders là sử dụng phân loại kNN . Phương pháp phân loại này – hay các phương pháp phân loại và phân cụm khác phụ thuộc rất nhiều vào định nghĩa một độ đo khoảng cách hay độ tương tự thích hợp . Distane meansure đơn giản và phổ biến nhất đó là Eucidean distane :

euclidean-distance

với n là số chiều (hay số features) và  và  là attributes thứ k của data objects x và y

Minkowski Distance là phương trình tổng quát của Euclidean Distance

minkowski-distance

Phụ thuộc vào giá trị của r , khoảng cách Minkowski sẽ được gọi với những tên gọi riêng : Với r=1 , là city block ( Manhattan , taxicab hay L1 norm ) . Với r=2 , khoảng cách Euclidean …

Một phương pháp rất phổ biến khác xem xét các items như các vector không gian n-chiều , và tính toán độ tương tự của chúng như là cosine giữa các góc :

cosine-distance

với . là vector dot product và ||x|| là độ lớn của vector x . Độ tương tự này được biết đến như là cosine similarity hay L2 Norm

  • Sampling

Sampling là kĩ thuật chính được sử dụng trong Data mining để chọn một tập các dữ liệu liên quan từ một tập lớn dữ liệu . Sampling có thể được sử dụng bởi vì xử lý toàn bộ dataset tốn kém mặt tính toán . Nó cũng có thể được sử dụng để tạo ra training testing datasets .

Vấn đề chủ yếu của sampling đó là tìm được tập con từ tập dữ liệu gốc làm sao mà tượng trưng cho toàn bộ bộ dữ liệu . Kĩ thuật sampling đơn giản nhất đó là random sampling  , xác suất chọn bất kì 1 item nào là như nhau . Có những phương pháp phức tạp hơn như stratified sampling

  • Reducing Dimensionality

Features trong data set có thể được định nghĩa trong một không gian có số chiều lớn , và thông tin thì rất rải rác , chỉ có môt số features trong mỗi object là có giá trị . Những khái niệm về mật độ và khoảng cách giữa các điểm, mà quan trọng cho clustering và phát hiện outlier, trở nên ít ý nghĩa trong không gian rất chiều . Điều này được biết đến là Curse of Dimensionality . Kĩ thuật giảm chiều sẽ giúp chúng ta vượt qua được vấn đề này bằng cách chuyển không gian nhiều chiều ban đầu sang không gian có số chiều nhỏ hơn .

Hai phương pháp giảm chiều được sử dụng nhiều nhất trong ngữ cảnh RS là : Principal Component Analysis (PCA) Singular Value Decomposition (SVD) .

  1. Content-based RS

Hệ thống sẽ học cách gợi ý items mà tương tự với items mà user đã từng thích trong quá khứ . Độ tương tự của các items được tính toán dựa vào features . Ví dụ , nếu một user từng đánh giá một phim hài cao , thì hệ thống sẽ có thể sẽ gợi ý các phim hài khác cho người dùng . Quá trình recommendation đơn giản có thể là nối giữa attributes của user profile và các attributes của content object

3.1. Kiến trúc của Content-based RS

content-based-recommender

Content-based RSs cần một kĩ thuật đúng đắn để biểu diễn item , sinh ra user profile và một phương pháp để so sánh giữa user profile và item . Quá trình recommendation sẽ được thực thi qua 3 bước :

– CONTENT ANALYZER : Với những thông tin không có cấu trúc ( như text ) , một số bước tiền xử lý la cần thiết để thu được các thông tin có cấu trúc liên quan

– PROFILE LEARNER : Module này sẽ thu thập thông tin tượng trưng cho sở thích của user , cố gắng từ dữ liệu này , xây dựng user profile .

– FILTERING COMPONENT

Posted in Machine Learning

Doc2Vec hay Paragraph Vectors

Distributed representations of sentences and documents – Le & Mikolov, ICML 2014

Chúng ta trước đây đã thấy sức mạnh kì diệu của word2vec học được cách biểu diễn phân tán (distributed representation) của một từ mà có thể giữ lại ngữ nghĩa của từ đó . Trong bài báo này , Le và Mikolov mở rộng ứng dụng để có thể tính toán biểu diễn phân tán cho sentences, paragraphs, hay kể cả một văn bản .Họ chỉ ra rằng model kết quả của họ thực hiện tốt hơn các state-of-the-art trước đó trong một bài toán phân loại văn bản và phân tích ngữ nghĩa .

Các thuật toán phân loại hay phân cụm thường xuyên đòi hỏi tập văn bản đầu vào biểu diẽn dưới dạng một vector có độ dài cố định (fixed length vector). Các mô hình phổ biến đó là bag-of-words và bag-of-n-grams . Bag-of-words đương nhiên là làm mất đi ngữ nghĩa có thể tới từ thứ tự của các từ . Bag-of-n-grams chỉ xem xét short context và không được tốt lắm nếu bới dữ liệu thưa thớt và  số chiều lớn.

Bag-of-words and bag-of-n-grams have very little sense about the semantics of the words or more formally the distances between the words. This means that words “powerful,” “strong” and “Paris” are equally distance despite the fact tha semantically, “powerful” should be closer to “strong” than “Paris.”

Các nhà nghiên cứu trước đây đã cố gắng kết hợp các distributed  word vectors  – ví dụ bằng cách sử dụng một trọng số trung bình của tất cả các từ trong một tài liệu, hoặc kết hợp các word vectors theo một thứ tự nhất định của cây phân tích cú pháp của một câu. Các phương pháp này cũng chịu việc mất mát thông tin về thứ tự từ , và sau này không dễ dàng để mở rộng câu .

Ghi nhớ rằng mô hình học word vector mà context xung quanh từ được sử dụng để dự đoán từ đó :

Our approach for learning paragraph vectors is inspired by the methods for learning the word vectors. The inspiration is that the word vectors are asked to contribute to a prediction task about the next word in the sentence. So despite the fact that the word vectors are initialized randomly, they can eventually capture semantics as an indirect result of the prediction task. We will use this idea in our paragraph vectors in a similar manner. The paragraph vectors are also asked to contribute to the prediction task of the next word given many contexts sampled from the paragraph.

Các từ vẫn được ánh xạ với các vectors duy nhất như trước . Thêm vào đó mỗi paragraph (hay document, nếu làm việc ở document level) cũng được kết nối tới một vector duy nhất . Word vectors nằm trong cột của matrix W, và paragraph vectors nằm trong cột của matrix D.

Thay đổi duy nhất vs quá trình học word vector là paragraph vector được nối với các word vectos để dự đoán từ kế tiếp trong một ngữ cảnh. Bối cảnh được cố định độ dài và lấy mẫu từ một cửa sổ trượt trên một đoạn. Paragraph vectors được chia sẻ cho tất cả các cửa sổ được tạo ra từ cùng một đoạn, nhưng không toàn bộ paragraphs . Ngược lại, word vector chia sẻ trên tất cả các đoạn văn.

The paragraph token can be thought of as another word. It acts as a memory that remembers what is missing from the current context – or the topic of the paragraph. For this reason, we often call this model the Distributed Memory Model of Paragraph Vectors (PV-DM).

Tại mỗi bước trong việc huấn luyện một context có  chiều dài cố định được lấy mẫu từ một đoạn ngẫu nhiên và được sử dụng để tính toán error gradient để cập nhật các thông số trong mô hình. Với N đoạn mỗi ánh xạ tới p chiều  và M từ  mỗi ánh xạ tới q chiều mô hình này có tổng cộng N x p + M x q tham số  (không bao gồm các tham số softmax).

Một khi họ đã được đào tạo, các paragraph vectors có thể được sử dụng như là các đặc trưng cho các đoạn văn trong bất kỳ công việc học máy . Vào thời gian dự đoán, một bước suy luận được thực hiện để tính toán paragraph  vector cho một paragraph  mới (chưa từng được thấy trước đây) . Trong thời gian này bước các thông số cho phần còn lại của mô hình (word vector W và trọng sốsoftmax U và b) được cố định.

In summary, the algorithm itself has two key stages: 1) training to get word vectors W, softmax weights U, b and paragraph vectors D on already seen paragraphs; and 2) “the inference stage” to get paragraph vectors D for new paragraphs (never seen before) by adding more columns in D and gradient descending on D while holding W, U, b fixed. We use D to make a prediction about some particular labels using a standard classifier, e.g., logistic regression.

Một biến thể của sơ đồ bên trên là bỏ qua context words  trong các đầu vào (tức là, do away with cửa sổ trượt), và thay vào đó buộc các mô hình để dự đoán từ lấy mẫu ngẫu nhiên từ đoạn ở đầu ra.

In reality, what this means is that at each iteration of stochastic gradient descent, we sample a text window, then sample a random word from the text window and form a classification task given the Paragraph Vector… We name this version the Distributed Bag of Words version of Paragraph Vector (PV-DBOW), as opposed to Distributed Memory version of Paragraph Vector (PV-DM) in the previous section.

PV-DM thực hiện tốt hơn so với PV-DBOW, nhưng  kết hợp cả hai PV-DM và PV-DBOW cho chúng ta kết quả tốt nhất :

PV-DM is consistently better than PV-DBOW. PV-DM alone can achieve results close to many results in this paper. For example, in IMDB, PV-DM only achieves 7.63%. The combination of PV-DM and PV-DBOW often work consistently better (7.42% in IMDB) and therefore recommended.

Cùng xem Paragraph Vectors thực hiện tốt như thế nào trong bài toán sentiment analysis và paragraph classification .

Kết quả thực nghiệm

Bộ dữ liệu Stanford Sentiment Treebank bao gồm 11855 câu đã được gán nhãn từ rất tiêu cực cho đến rất tích cực trong scale từ 0.0 cho 1.0. Sử dụng một window size là 8, và một vector mà là ghép nối từ PV-DBOW và một từ PV-DM (cả 2 đều có 400 chiều ), các tác giả đã đạt được các kết quả như sau :

Mặc dù sự thật là it không cần đòi hỏi phân tích cú pháp , paragraph vectors thực thi tốt hơn tất cả các baselines  2.4% (relative improvement 16%) so sánh với kết quả tốt nhất tiếp theo.

Tất  nhiên paragraph vectors không hạn chế ở mức độ câu  , như thế các tác giả có thể áp dụng kĩ thuật này tới bộ dữ liệu 100,000 movie reviews lấy từ IMDB…

We learn the word vectors and paragraph vectors using 75,000 training documents (25,000 labeled and 50,000 unlabeled instances). The paragraph vectors for the 25,000 labeled instances are then fed through a neural network with one hidden layer with 50 units and a logistic classifier to learn to predict the sentiment. At test time, given a test sentence, we again freeze the rest of the network and learn the paragraph vectors for the test reviews by gradient descent. Once the vectors are learned, we feed them through the neural network to predict the sentiment of the reviews.

Một lần nữa , paragraph vectors tốt hơn hẳn các state-of-the-art trước , với  15% cải tiến tương đối (relative improvement):

Lukas Vermeer của trang Booking.com từng nói “Nếu bạn hỏi một nhà khoa học dữ liệu rằng làm sao để xác định khi nào review là tích cực hay tiêu cực , họ sẽ bắt đầu nói về sentiment analysis… nhưng thật là lộn xộn trong thế giới thực . Đây là cách chung tôi giải quyết nó ở trang Booking.com:”

Với thực nghiệm thứ 3 , tác giá nhìn vào top 10 kết quả của mỗi query trong 1 triệu queries phổ biến nhất trong search engine, và rút ra paragraphs từ đó . Họ tạo ra tập 3 paragraphs: hai lấy từ kết quả của cùng truy vấn, và một từ một truy vấn khác

Our goal is to identify which of the three paragraphs are results of the same query. To achieve this, we will use paragraph vectors and compute the distances between the paragraphs. A better representation is one that achieves a small distance for pairs of paragraphs of the same query, and a large distance for pairs of paragraphs of different queries.

Như thế thực nghiệm này là một cách đánh giá liệu paragraph vectors theo cách nào đó có thể giữ lại ý nghĩa của paragraphs như word vectors đã làm được …

The results show that Paragraph Vector works well and gives a 32% relative improvement in terms of error rate. The fact that the paragraph vector method significantly outperforms bag of words and bigrams suggests that our proposed method is useful for capturing the semantics of the input text.

Để sử dụng được Paragraph vector trên java có thể tham khảo : http://deeplearning4j.org/doc2vec.html

Lược dịch từ : https://blog.acolyer.org/2016/06/01/distributed-representations-of-sentences-and-documents/

Posted in Machine Learning

Word2vec : The amazing power of word vectors

Word vector là gì?

Nói đơn giản , nó chỉ là một vector của các trọng số biểu diễn cho từ đó . Trong dạng biểu diễn  1-of-N (hay ‘one-hot’) mã hoá các phần tử trong vector kết hợp với một từ trong vocabulary. Cách mã hóa của một từ cho trước chỉ đơn giản là vector trong đó các phần tử liên quan được thiết lập là một, và tất cả các phần tử  khác là số không.

Giả sự bộ từ điển của chúng ta chỉ gồm có 5 từ . Chúng ta có thể mã hoá từ  ‘Queen’ như sau:

Sử dụng loại mã hóa này , không có cách so sánh có ý nghĩa giữa hai word vectors hay kiểm tra bằng nhau .

Trong word2vec , một biểu diễn phân tán(distributed representation) của một từ được sử dụng . Sử dụng một vector với vài trăm chiều . Mỗi từ được biểu diễn bới tập các trọng số của từng phần tử trong nó. Như thế thay vì kết nối  one-to-one giữa các phần từ trong vector và 1 từ , biểu diễn từ sẽ là dàn trải tất cả các thành phần của vector , và mỗi phần tử trong vector sẽ góp phần định nghĩa nhiều từ khác

Word2vec có thể được nhìn nhận kiểu kiểu như thế này :

Mỗi vector như vậy cũng đại diện cho một cách tóm lược của ý nghĩa của một từ. Và như chúng ta sẽ thấy tiếp theo, chỉ đơn giản bằng cách kiểm tra một ngữ liệu lớn nó có thể học word vectors , ta có thể nắm bắt các mối quan hệ giữa các từ trong một cách đáng ngạc nhiên. Chúng ta cũng có thể sử dụng các vector là đầu vào cho một mạng nơ ron.

Suy luận với word vectors

We find that the learned word representations in fact capture meaningful syntactic and semantic regularities in a very simple way. Specifically, the regularities are observed as constant vector offsets between pairs of words sharing a particular relationship. For example, if we denote the vector for word i as xi, and focus on the singular/plural relation, we observe that xapple – xapples ≈ xcar – xcars, xfamily – xfamilies ≈ xcar – xcars, and so on. Perhaps more surprisingly, we find that this is also the case for a variety of semantic relations, as measured by the SemEval 2012 task of measuring relation similarity.

Các vectơ rất tốt ở khía cạnh trả lời câu hỏi tương tự của các hình thức “a is to b as c is to?”. Ví dụ , man is to woman as uncle is to ? (aunt) chỉ cần sử dụng khoảng cách cosine

Ví dụ , đây là vector offsets cho 3 cặp từ trong mối quan hệ giới tính :

Và đây là mối quan hệ số nhiều / số ít :

Việc tương tác với vector cho phép chúng ta trả lời câu hỏi  “King – Man + Woman = ?” và sẽ nhận được kết quả “Queen” !  Đây quả là điều đáng ghi nhớ khi mà chúng ta có được những kiến thức này đơn giản chỉ nhìn vào các từ trong các context mà không có thêm một thông tin ngữ nghĩa gì cả .

Somewhat surprisingly, it was found that similarity of word representations goes beyond simple syntatic regularities. Using a word offset technique where simple algebraic operations are performed on the word vectors, it was shown for example that vector(“King”) – vector(“Man”) + vector(“Woman”) results in a vector that is closest to the vector representation of the word Queen.

Vectors cho King, Man, Queen, & Woman:

Kết quả của  King – Man + Woman = ?

Đây là 1 vài kết quả đạt được sử dụng cùng một kĩ thuật :

Đây là mối quan hệ đất nước – thủ đổ trong phép chiếu PCA 2 chiều :

Đây là một vài ví của  ‘a is to b as c is to ?’ trả lời bởi word vectors:

Chúng ta có thể dùng phép cộng vector để hỏi câu hỏi như “German + airlines” bằng cách tìm từ nào gần nhất:

Word vectors với quan hệ ngữ nghĩa như thế có thể được sử dụng để cải thiện rất nhiều các ứng dụng NLP như  machine translation, information retrieval and question answering systems, và các ứng dụng khác chưa được phát minh

Bài kiểm tra mối quan hệ  ngữ nghĩa – cú pháp for understanding of a wide variety of relationships as shown below. Sử dụng 640-dimensional word vectors, một skip-gram model đạt được 55% độ chính xác ngữ nghĩa và 59% độ chính xác cú pháp.

Quá trình học word vectors

Mikolov không phải là người đầu tiên sử dụng continuous vector biểu diễn các từ ,nhưng họ đã làm là chỉ ra cách để giảm thiểu độ phức tạp tính toán của quá trình học để biểu diễn – tạo ra nó thực hiện được để học high dimensional word vectors trong một lượng cực lớn dữ liệu. Ví dụ , “We have used a Google News corpus for training the word vectors. This corpus contains about 6B tokens. We have restricted the vocabulary size to the 1 million most frequent words…”

Độ phức tạp của  neural network language models (feedforward or recurrent) tới từ các tầng ẩn không tuyển tính (non-linear hidden layer(s)).

While this is what makes neural networks so attractive, we decided to explore simpler models that might not be able to represent the data as precisely as neural networks, but can posssible be trained on much more data efficiently.

Hai kiến trúc mới được đề xuất: Continuous Bag-of-Words model, và  Continuous Skip-gram model. Hãy cùng nhìn vào mô hình continuous bag-of-words (CBOW) trước .

Một đoạn trong bài báo có viết : “The recently introduced continuous Skip-gram model is an efficient method for learning high-quality distributed vector representations that capture a large number of precises syntatic and semantic word relationships.” Tưởng tượng một cửa sổ trượt qua text , nó sẽ bao gồm từ trung tâm mà đang focus , cùng với đó là 4 từ trước nó và 4 từ theo sau nó :

The context words form the input layer. Mỗi từ sẽ được mã hoá kiểu one-hot , như thế nếu vocabulary size là V thì sẽ là  V-dimensional vectors với chỉ một phần tử được đặt là 1 và tất cả các phần tử khác là 0 . Như thế sẽ chỉ có một tầng ẩn và một output layer.

Mục đích huẩn luyện đó là làm cục đại hoá xác suất có điều kiện  nhìn thấy output thật sự (the focus word) cho trước bởi  input context words. Trong ví dụ này , cho input(“an”, “efficient”, “method”, “for”, “high”, “quality”, “distributed”, “vector”) chúng ta muốn cực đại hoá xác suất lấy  đc từ “learning” là output.

Bởi vì input vector của chúng ta có dạng one-hot, nhân  input vector với ma trận trọng số  W1 hay đơn giản là lấy hàng  từ W1.

Cho trước  C input word vectors, “activation function: cho lớp ẩn tính tổng các hàng”hot” trong W1, và rồi chia cho C để lấy trung bình .

This implies that the link (activation) function of the hidden layer units is simply linear (i.e., directly passing its weighted sum of inputs to the next layer).

Từ  hidden layer cho tới output layer, ma trận trọng số thứ 2  W2 có thể được sử dụng để tính toán score cho từng từ trong vocabulary, và softmax có thể được sử dụng để phân bổ lại giá trị cho các từ .

Mô hình skip-gram là một mô hình đối lập hoàn toàn với mô hình CBOW . Nó được xây dựng  tập trung vào từ như một single input vector, và  target context words bây giờ là output layer:

Activation function cho hidden layer  đơn giản sao chép hàng tương ứng trong ma trận trọng số  W1 (linear) mà chúng ta đã thấy trước đó . Tại output layer , chúng ta cho ra C multinomial distributions thay vì chỉ một . Mục đích huấn luyện sẽ là tối thiểu hoá tổng lỗi dự đoán cho tất cả các context words trong  output layer. Trong ví dụ của chúng ta , đầu vào sẽ là  “learning”, và chúng ta sẽ mong muốn là sẽ nhìn thấy (“an”, “efficient”, “method”, “for”, “high”, “quality”, “distributed”, “vector”) tại output layer.

Tối ưu hoá

Phải cập nhật tất cả output vector  cho tất cả các từ trong tập huấn luyện rất là tốn kém ….

To solve this problem, an intuition is to limit the number of output vectors that must be updated per training instance. One elegant approach to achieving this is hierarchical softmax; another approach is through sampling.

Hierarchical softmax  sử dụng cây nhị phân để biết diễn tất cả các từ trong vocabulary. Mỗi từ là một lá trong cây . Với mỗi lá , tồn tại duy nhất một đường từ gốc tới lá này , như thế đường này sẽ được sử dụng để ước lượng xác suất mối từ biểu diễn bởi lá .

“We define this probability as the probability of a random walk starting from the root ending at the leaf in question.”

The main advantage is that instead of evaluating V output nodes in the neural network to obtain the probability distribution, it is needed to evaluate only about log2(V)words… In our work we use a binary Huffman tree, as it assigns short codes to the frequent words which results in fast training.

Negative Sampling chỉ đơn giản là chúng ta chỉ cập nhật sample của output word mỗi vòng lặp . Target output word sẽ được giữ trong sample và được cập nhật và chúng ta sẽ thêm một vài (non-target) từ như  negative samples.

“A probabilistic distribution is needed for the sampling process, and it can be arbitrarily chosen… One can determine a good distribution empirically.”

Milokov cũng sử dụng một cách tiếp cận subsampling đơn giản để chống lại sự mất cân bằng giữa các từ hiếm và thường xuyên trong tập huấn luyện (ví dụ, “in”, “the”, and “a” cung cấp ít giá trị thông tin hơn các từ hiếm ). Mỗi từ trong tập huấn luyện được loại bỏ với một xác suất P(wi)

f(wi là tần suất của từ  wi và t là 1 ngưỡng được chọn , thường xung quanh 10-5)

DeepLearning4j

Loading Data

Bây giờ tạo và đặt tên cho một class mới trong Java . Say đó , bạn sẽ cho raw sentences vào trong file .txt của bạn , đưa chúng qua iterator của bạn , và một số loại tiền xử lý , chẳng hạn chuyển đổi tất cả các từ về chữ thường .

        String filePath = new ClassPathResource("raw_sentences.txt").getFile().getAbsolutePath();

        log.info("Load & Vectorize Sentences....");
        // Strip white space before and after for each line
        SentenceIterator iter = new BasicLineIterator(filePath);

Nếu bạn muốn tải dữ liệu text của bạn từ ngoài folder của project :

        log.info("Load data....");
        SentenceIterator iter = new LineSentenceIterator(
             new File("/Users/cvn/Desktop/file.txt"));
        iter.setPreProcessor(new SentencePreProcessor() {
            @Override
            public String preProcess(String sentence) {
                return sentence.toLowerCase();
            }
        });

 

Tokenizing the Data

Word2vec cần được cung cấp các từ hơn các các câu , nên bước tiếp theo sẽ là tách từ từ dữ liệu . Để tách từ từ dữ liệu , ta có thể dùng space để nhận biết , ví dụ :

        // Split on white spaces in the line to get words
        TokenizerFactory t = new DefaultTokenizerFactory();
        t.setTokenPreProcessor(new CommonPreprocessor());

Nó sẽ cho chúng ta mỗi từ nằm trên một dòng

Training the Model

Chúng ta có thể tuỳ chỉnh mạng nơ ron Word2vec của chúng ta :

        log.info("Building model....");
        Word2Vec vec = new Word2Vec.Builder()
                .minWordFrequency(5)
                .iterations(1)
                .layerSize(100)
                .seed(42)
                .windowSize(5)
                .iterate(iter)
                .tokenizerFactory(t)
                .build();

        log.info("Fitting Word2Vec model....");
        vec.fit();

Tuỳ chỉnh các siêu tham số với ý nghĩa như sau :

  • batchSize là số từ chúng ta xử lý trong một thời điểm.
  • minWordFrequency là số lần xuất hiện ít nhất phải xuất hiện trong bộ ngữ liệu . Ở đây , nếu mà một từ xuất hiện ít hơn 5 lần , nó sẽ không được học . Các từ phải xuất hiện trong nhiều ngữ cảnh(context) để học các feature hữu ích về nó . Trong một bộ ngữ liệu lớn , hoàn toàn hợp lý để tăng ngưỡng minimum này lên .
  • useAdaGrad – Adagrad tạo ra các gradient khác nhau cho từng feature . Ở đây chúng ta sẽ không quan tâm đến nó .
  • layerSize chỉ rõ số features trong word vector . Nó bằng với số chiều trong featurespace . Từ được biểu diễn bới 500 features sẽ trở thành một điểm trong không gian 500 chiều .
  • iterations : đây là số lần mà bạn cho phép mạng của bạn cập nhật các hệ số của nó cho 1 batch của dữ liệu . Quá ít iterations có nghĩa là có thể không có đủ thời gian để học tất cả , quá nhiều sẽ kiến thời gian huấn luyện của mạng lâu hơn .
  • learningRate là step size cho mỗi lần cập nhật các hệ số , như các từ được bố trí trong feature space.
  • minLearningRate là mức sàn của  learning rate. Learning rate như số lượng từ bạn huấn luyện giảm xuống . Nếu  learning rate co lại quá nhiều , mạng huấn luyện sẽ không hiệu quả . Nó giữ các hệ số biến đổi .
  • iterate bảo mạng rằng batch của dataset nào nó đang huấn luyện.
  • tokenizer cho các từ vào  các batch hiện tại .
  • vec.fit() bắt đầu huấn luyện.

Evaluating the Model, Using Word2vec

Bước tiếp theo sẽ là đánh giá chất lượng feature vectors của bạn .

        // Write word vectors
        WordVectorSerializer.writeWordVectors(vec, "pathToWriteto.txt");

        log.info("Closest Words:");
        Collection<String> lst = vec.wordsNearest("day", 10);
        System.out.println(lst);
        UiServer server = UiServer.getInstance();
        System.out.println("Started on port " + server.getPort());
        
        //output: [night, week, year, game, season, during, office, until, -]

Dòng vec.similarity("word1","word2") sẽ trả lại độ tương đồng cosine của hai từ .Càng gần 1 , thì mạng nhận thức được 2 từ càng tương đồng  . Ví dụ như:

        double cosSim = vec.similarity("day", "night");
        System.out.println(cosSim);
        //output: 0.7704452276229858

Với vec.wordsNearest("word1", numWordsNearest), cho phép bạn lấy ra các từ tương tự về mặt ngữ nghĩa . Bạn có thể đặt số từ gần nhất mà bạn muốn ở tham số thứ 2 của wordsNearest. Ví dụ như:

        Collection<String> lst3 = vec.wordsNearest("man", 10);
        System.out.println(lst3);
        //output: [director, company, program, former, university, family, group
                               , such, general]

Saving, Reloading & Using the Model

Bạn sẽ muốn lưu lại model của bạn . Các thông thường để lưu models trong Deeplearning4j là thông qua serialization utils (Java serialization  tương tự như Python pickling , biến đổi một đối tượng sang series of bytes).

        log.info("Save vectors....");
        WordVectorSerializer.writeFullModel(vec, "pathToSaveModel.txt");

Nó sẽ lưu các vectors sang một file là  words.txt mà sẽ xuất hiện trong root của thư mục mà Word2vec được huấn luyện. Đầu ra của file sẽ phải có mỗi từ một dòng theo sau đó sẽ là một chuỗi các từ mà cùng nhau biểu diễn features vector của từ này .

Để làm việc tiếp với các vectors, đơn giản chỉ cần goi các phương thức trong  vec như sau:

Collection<String> kingList = vec.wordsNearest(Arrays.asList("king", "woman"), 
Arrays.asList("queen"), 10);

Ví dụ kinh điển của Word2vec’s là “king – queen = man – woman” và “king – queen + woman = man”.

Ví dụ bên trên sẽ cho ra 10 từ gần nhất với vector  king - queen + woman, mà sẽ phải bao gồm  man. Tham số đầu tiên của  wordsNearest sẽ có các từ “positive” kingwoman, sẽ có dấu + kết hợp chúng , tham số thứ 2 sẽ bao  gồm từ “negative” queen, mà sẽ kết hợp với dấu – ; và tham số thứ 3 là độ dài của list các từ gần nhất bạn muốn nhìn thấy .

Bạn có thể reload vectors như sau :

        Word2Vec word2Vec = WordVectorSerializer.loadFullModel("pathToSaveModel.txt");

Bạn có thể sử dụng Word2vec như một  lookup table:

        WeightLookupTable weightLookupTable = wordVectors.lookupTable();
        Iterator<INDArray> vectors = weightLookupTable.vectors();
        INDArray wordVector = wordVectors.getWordVectorMatrix("myword");
        double[] wordVector = wordVectors.getWordVector("myword");

Nếu một từ không có trong vocabulary, Word2vec returns zeros.

Importing Word2vec Models

Google News Corpus model we use to test the accuracy of our trained nets is hosted on S3. Người dùng với phần cứng hiện tại có thể tốn rất lâu để huấn luyện bộ ngữ liệu lớn , thay vào đó có thể đơn giản download nó về

Nếu bạn huấn luyện với  C vectors hoặc Gensimm, có thể import model như sau :

    File gModel = new File("/Developer/Vector Models/
                               GoogleNews-vectors-negative300.bin.gz");
    Word2Vec vec = WordVectorSerializer.loadGoogleModel(gModel, true);

Với một models rất lớp , bạn có thể gặp vấn đề với heap space . Google model sẽ cần tới 10G RAM , và JVM chỉ có thể chạy tới 256 MB RAM, như thế bạn sẽ phải điều chỉnh heap space của bạn . Với IntelliJ có thể làm

    //Click:
    IntelliJ Preferences > Compiler > Command Line Options 
    //Then paste:
    -Xms1024m
    -Xmx10g
    -XX:MaxPermSize=2g
    // Or
    Click File->Settings->Build,Execution,Deployment->Complier->Build 
process heap size


 Nếu bạn truy vấn Word2vec model một từ không xuất hiện trong tập huấn luyện , nó sẽ trả về null

Doc2vec & Other NLP Resources

Other Deeplearning4j Tutorials

Word2Vec in Literature

It's like numbers are language, like all the letters in the language are turned 
into numbers, and so it's something that everyone understands the same way.You 
lose the sounds of the letters and whether they click or pop or touch the palate,
or go ooh or aah, and anything that can be misread or con you with its music or 
the pictures it puts in your mind, all of that is gone, along with the accent, 
and you have a new understanding entirely, a language of numbers, and everything 
becomes as clear to everyone as the writing on the wall. So as I say there comes 
a certain time for the reading of the numbers.
                                     -- E.L. Doctorow, Billy Bathgate
Posted in Khác

Linear Regression – Hồi quy tuyến tính

  1.  Linear Regression

Trong thống kê , chúng ta sử dụng hai cái tên khác nhau cho nhiệm vụ nối một số input features thành một số giá trị output : chúng ta sử dụng từ Regression khi output là giá trị thực , và Classification khi output là một trong tập rời rạc các classes . Linear Regression là một trong những kĩ thuật cơ bản và quan trọng để dự đoán giá trị cho một attribute(y) .

Ý tưởng của Linear Regression là chúng ta sẽ được cho một tập các observations , mỗi observations sẽ được liên kết tới một vài features , chúng ta sẽ muốn dự đoán giá trị thực cho mỗi observations . Một ví dụ nổi tiếng về dự đoán giá nhà (Levitt and Dubner (2005)) chỉ ra rằng những từ được sử dụng trong những quảng cáo bất động sản có thể là một dự đoán tốt xem một ngôi nhà sẽ được bán với giá cao hơn hay ít hơn so với giá chào bán của nó . Họ chỉ ra rằng , ví dụ , một ngôi nhà  được quảng cáo bất động sản có những từ như fantastic , cute , hoặc charming , thường có xu hướng bán với giá thấp hơn , trong khi những ngôi nhà có quảng cáo có những từ như maple granite thường bán với giá cao hơn . Giả thuyết của họ là các môi giới sử dụng các từ tích cực mơ hồ như fantastic để che giấu những sự thiếu hụt những định lượng tích cực trong ngôi nhà .

Một vài dữ liệu chúng ta tự tạo ra :

Số các tính từ mơ hồ Giá bán được cao hơn giá mời chào
4 0
3 $1000
2 $1500
2 $6000
1 $14000
0 $18000

 

Hình dưới mô tả các điểm dữ liệu trong dữ liệu tự tạo của chúng ta , với số các tính từ mơ hồ trong trục x , và giá trong trục y . Chúng ta sẽ vẽ được một regression line , mà có thể phù hợp tốt nhất với dữ liệu chúng ta quan sát được .

1

Với Linear regression một biến như ví dụ trên , chúng ta có thể tìm một phương trình có dạng

price = w0 + w1 * Num_Adjectives

Khi có nhiều hơn một feature , được gọi là multiple linear regression . Ví dụ , giá một ngôi nhà có thể phụ thuộc vào rất nhiều các yếu tố như số ngồi nhà chưa bán trong thị trường , tỷ lệ thế chấp trung bình . Chúng ta có thể coi những yếu tố này là một biến , độ quan trọng các yếu tố sẽ là weight của nó

price = w0 + w1 * Num_Adjectives + w2 * Mortgage_Rate + w3* Num_Unsold_Houses

Trong xử lý ngôn ngữ tự nhiên , chúng ta thường gọi các yếu tố dự đoán như số tính từ mơ hồ là các feature . Chúng ta sẽ biểu diễn mỗi observation( mỗi một ngôi nhà để bán) bằng một vector của những features này . Giả sử một ngôi nhà có một tính từ mơ hồ trong quảng cáo của nó , và tỷ lệ thế chấp trung bình là 6.5 và có 10,000 ngôi nhà chưa bán trong thành phố . Như thế feature vector cho ngôi nhà này sẽ là f = (1,6.5,10000) . Giả sử chúng ta sẽ học được weight vector là w =(w0,w1,w2,w3) = (18000,-5000,-3000,-1.8) . Như thế giá trị dự đoán cho ngôi nhà này sẽ tính bằng cách nhân các giá trị feature với weight của nó :

2

Thông thường , chúng ta sẽ giả vờ như là sẽ có thêm một feature mang giá trị 1 , gọi là Intercept feature , khi đó chúng ta có thể biểu diễn linear regression dự đoán cho y sẽ là :

3         2 . Quá trình học của linear regression

Làm sao để học ra các trọng số weights cho linear regression . Bằng trực giác , chúng ta sẽ mong muốn chọn được các weights sao cho giá trị y ước lượng sẽ gần nhất với giá trị thực tế chúng ta nhìn thấy trong tập training set .

Chúng ta có thể sử dụng sum squared cost function , định nghĩa như sau :

4

Chúng ta sẽ chọn tập weights tối ưu để làm cho sum-squared error nhỏ nhất . Sum Squared error cost function là một lựa chọn có lý do , và nó hoạt động tốt trong hầu hết các vấn đền , cho hầu hết bài toán regression . Có những cost functions khác hoạt động cũng tốt , nhưng sum squared error cost function là một trong những cost function sử dụng nhiều nhất cho bài toán regression [5]

Nếu chúng ta cho tất cả tập dữ liệu huấn luyện vào một ma trận X , với mỗi hàng trong ma trận sẽ là vector features ứng với observations x(i) (nên nhớ cột 1 của ma trận X sẽ mang giá trị 1 bởi vì chúng ta đã giả sử extra value bên trên) , và chúng ta sẽ cho hết các giá trị y vào  vector y . Như thế chúng ta sẽ tính ra được W bằng công thức :

5

 Ngoài Normal equation trên để tìm ra regression line , chúng ta có thể sử dụng gradrient descent . Đây cũng là một thuật toán thông dụng và không chỉ sử dụng trong linear regression [5] . So sánh giữa Gragient Descent và Normal Equation để tìm ra regression line

6

Nếu XT X không thể có nghịch đảo (khi det(XT X)=0)  , chúng ta sẽ xem xét các feature , xem các feature có phụ thuộc vào nhau không : Vì dụ có 1 feature là size in feet , 1 feature là size in meters squared , như thế 2 feature này sẽ không độc lập với nhau . Việc của chúng ta là sẽ xoá đi 1 features .

  • .Một vài vấn đề trong linear regression
    • Linear regression for classification [6]

7Scaling input features

3 . Thực thi

Chúng ta biết rằng , có thể tính W bằng công thức bên trên

8

Như vậy chúng ta sẽ đi xây dựng các phép toán trên ma trận : Nhân ma trận , chuyển vị ma trận , nghịch đảo ma trận

Object matrix

9

Class các phép toán với Matrix

Nhân hai ma trận

10

Chuyển vị ma trận

11

Nghịch đảo ma trận

Định nghĩa : Một ma trận nghịch đảo của ma trận vuông A là

A-1 sao cho A . A-1 = I

Công thức ma trận chuyển vị :

A-1 = 1/detA * adj(A^T)

12

Có thể thấy nếu det A = 0 thì không tồn tại ma trận nghịch đảo

Ta có thể tính định thức bằng quy nạp

* Nếu n = 1 Þ a = (a) Þ detA = a.

* Nếu n > 1 thì:

delA = (-1)i+1ai1|Ai1| + (-1)i+2ai2|Ai2| + … + (-1)i+jaij|Aij|+… + (-1)i+nain|Ain|.

Tức là ta tính định thức bằng cách khai triển theo dòng thứ i.

Trong đó:

* (-1)i+jaij|Aij| là phần bù đại số của aij.

* (-1)i+j  là dấu chỉ số của phần tử ở dòng i cột j.

* aij là phần tử ở dòng i cột j.

* |Aij| là định thức con được lập bằng cách bỏ dòng i cột j.

Tuy nhiên : + Một định thức cấp 3 ta khai triển được 3 định thức cấp 2.

+ Một định thức cấp 4 ta khai triển được 4 định thức cấp 3.

Như vậy: một định thức cấp n ta khai triển được (n!)/2 định thức cấp 2.

Nếu n>10 việc tính toán định thức rất chậm , dẫn đến việc tính toán ma trận nghịch đảo cũng thế

Chúng ta sẽ tìm hiểu một phương pháp có độ phức tạp  O(n^2.3) để tìm ma trận nghịch đảo của một ma trận vuông .

LU Decompostion

            Các ma trận vuông có thể được phân rã thành tích của một ma trận lower triangular và một ma trận upper triangular matrix U

A = L U

Ví dụ ma trận A 3*3

13

Chúng ta sẽ có 9 phương trình với 12 ẩn . Để phương trình có nghiệm duy nhất , chúng ta sẽ set các phần tử trên đường chéo của L là 1

14

Như thế chúng ta sẽ giải hệ phương trình 9 ẩn ,9 phương trình

15

Như thế thì :

16

17

Chúng ta có thể tổng quát hoá công thức U và L như sau

18

19

Thuật toán giả mã phân tích A thành L và U

 

 

lu

Giả sử chúng ta phân tích được A = L . U

Như thế det A = det L . det U

Mà hàng chéo của L = 1 nên det A = det U = tích hàng chéo của U

Nếu u jj  = 0 sẽ dẫn tới det U = 0 = det A => không có ma trận nghịch đảo

Giả sử ta có thể phân tích được A = L . U

với L : Lower triangular matrix

U : Upper triangular matrix

 

Capture3.JPG

Ví dụ : Sử dụng LU decompostion để tìm nghịch đảo của ma trận A

20

Chúng ta có thể tính ra được ma trận L với U như sau

21

Ta sẽ đi giải phương trình : L Z = I

Với cột 1 của Z và I

22

Sẽ cho ta phương trình :

23

Ta sử dụng thuật toán “forward substitution” từ phương trình đầu đến cuối sẽ ra

24

Như thế có thể viết được thuật toán forward substitution giải Phương trình L z = i

Capture

Cột 1 của Z sẽ là :

25

Giờ đi giải phương trình U   = Z

Với cột 1 của Z :

26

 

Thuật toán backward substitution sẽ bắt đầu từ phương trình thứ 3 ngược về :

27

28

Như thế , chúng ta có thể viết được thuật toán back substitution giải phương trình U x = d

 

Capture1

Như thế cột đầu tiên của nghịch đảo của A sẽ là :

29

Tương tự , giải các phương trình

30

31

Như thế :

32

Chúng ta có thể xác nhận lại bằng cách :

33

Sau khi viết được hàm tính toàn L, U từ A . Rồi từ  L , U tính toán nghịch đảo
Ta có thể tính được W 1 cách dễ dàng :

4. Đánh giá

  • Mean absolute error ( MAE)

MAE là đại lượng dùng để meansure độ gần của dự đoán với giá trị outcomes thực tế . Công thức của MAE như sau : [4]

36

Trong đó ,  là giá trị dự đoán và  là giá trị thực tế

  • . Root Mean Squared Error ( RMSE )

Căn của trung bình tổng các lỗi bình phương [3]

37

Tham khảo :
[1] Steven Chapra and Raymond Canale, Numerical Methods for Engineers, Fourth Edition, McGraw-

Hill, 2002 (see Sections 10.1-10.2).

[2] Jurafsky and Martin , Speech And Language Processing , Second Edition ,  2007 (Chapter 6 – Hidden Markov and maximum entropy models)

[3] http://statweb.stanford.edu/~susan/courses/s60/split/node60.html

[4] https://en.wikipedia.org/wiki/Mean_absolute_error

[5] Machine Learning , Andrew NG

[6] Machine Learning , Caltech

Câu hỏi

  1. Những dự án mà công ty mình có dùng regression , các feature chọn ra như thế nào , định lượng ra sao , kết quả thực tế như thế nào ?
  2. Với những feature hay dữ liệu không phải dạng số . Có cách nào có thể chuyển được sang số để dùng linear regression như dữ liệu ví dụ dưới đâyzz.png
  3. Với việc làm việc với vector , việc scaling dữ liệu luôn luôn cần thiết ?
Posted in Khác

Sử dụng LibSvm trong Java

LibSvm có file jar để có thể chạy trong chương trình Java . Tuy nhiên chỉ có 1 số hàm được cung cấp như hàm : svm-train  , svm-predict  . Không có hàm để train tìm tham số tốt nhất . Vì thế chúng ta sẽ phải chạy cmd để tìm tham số tốt nhất . Sau khi tìm được tham số tốt nhất và train ra model . Chúng ta sẽ đi xây một thư viện Java cung cấp API phân loại 1 chuỗi String nội dung bài báo .

Load model từ filePath

model = svm.svm_load_model(filePath);

Xây dựng vector của chuỗi String bài báo

Sẽ có dạng svm_node[] nodes

Khai báo :  svm_node[] nodes = new svm_node[nodes size];

Với mỗi node trong nodes , set node.index là tên feature và node.index là giá trị của feature này . Mỗi node sẽ có index giống index của features định dạng libsvm.Có value sẽ là giá trị features định dang libsvm(Phải scaling giống như cách scaling  từ model file , bạn có thể scaling bằng phương pháp của bạn , hoặc dùng scaling của libsvm thì phải biết đc min_value , max_value của từng feature trong tập train để scaling lại test)

Sau đó có thể lấy ra nhãn bằng cách :

double label=svm.svm_predict(model,nodes);

Từ đây chúng ta có thể xây dựng 1 thư viện phân loại báo .

Mọi người có thể download thư viện ở đây : https://drive.google.com/file/d/0ByH8KMtJGmHHVi15dTlfdVRkc1E