Bí kíp lập trình ứng dụng thông minh – Natural language processing

2694

Xử lý ngôn ngữ tự nhiên (Natural language processing) – một công nghệ cho phép các ứng dụng phần mềm hiểu và xử lý ngôn ngữ của con người – đã trở nên khá phổ biến trong những năm gần đây.

Giờ đây, Google search đã có thể trả lời các câu hỏi với độ chính xác cao, Apple’s Siri hiểu rõ được các yêu cầu từ người dùng; và ngày càng nhiều các công ty sử dụng các mobile hoặc chat Bot trả lời thông minh để giao tiếp với khách hàng.

Thế nhưng các bạn có biết những ứng dụng “thông minh” trên hoạt động như thế nào không?

Bài viết sẽ chỉ ra những công nghệ được sử dụng cho các ứng dụng đấy nhằm giúp người đọc có cái nhìn khái quát về xử lý ngôn ngữ tự nhiên (Natural language processing). Từ đó mà chính bạn cũng có thể lập trình một ứng dụng phần mềm “thông minh”

Bắt đầu với thư viện Stanford của NLP (Stanford NLP Library)

Như những phần mềm “thông minh” khác, các ứng dụng của NLP được lập trình từ những thuật toán ngắn, đơn giản chạy song song nhau. Điều đó có nghĩa là nó thường sử dụng một thư viện bên ngoài (external library), nơi tất cả các thuật toán đã được triển khai và tích hợp sẵn.

Trong bài viết này, chúng ta sẽ nói về Stanford NLP Library, một thư viện xử lý ngôn ngữ tự nhiên cực kì mạnh mẽ cho các ứng dụng Java.

Có một thuật toán khá thú vị từ Stanford NLP Library được gọi là nhận dạng lời nói (Part of Speech – POS) tagger. Đây là một thuật toán có vai trò chuyển đổi lời nói của người dùng thành các text tương ứng. Ngoài ra, POS tagger còn phân loại các từ trong văn bản dựa trên các tính năng từ vựng và phân tích các từ này trong mối quan hệ với các từ khác xung quanh chúng nhằm tạo ra câu hoàn chỉnh.

Để hiểu được rõ hơn thuật toán này, bạn có thể xem thêm tại đây.

Để bắt đầu, chúng ta sẽ tạo một dự án Java mới (bạn có thể sử dụng IDE yêu thích của mình) và thêm thư viện NLN Stanford vào danh sách dependencies. Nếu bạn đang sử dụng Maven, chỉ cần thêm nó vào tập tin pom.xml của bạn:

Bởi vì app này sẽ phải có tính năng tự động trích xuất nội dung của một bài viết từ một trang web bất kì, bạn cần thêm vào hai dependencies sau:

Lọc và lấy thông tin

Như đã nói ở trên, bước đầu tiên của app là sẽ lấy thông tin từ bài viết của một web bất kì. Thế nhưng các bài viết trên mạng luôn có những thông tin không cần thiết (như videos, Links, Ads,….). Đó là lúc ta phải sử dụng thuật toán Boilerpipe.

Boilerpipe là một thuật toán rất mạnh mẽ và hiệu quả trong việc cắt lấy những content thông tin cần thiết bằng cách phân tích độ dài nội dung cũng như số câu chữ, tag, mật độ link. Boilerpipe chứng tỏ sự hiệu quả của mình không hề kém cạnh với các thuật toán phức tạp khác vốn rất tốn kém để viết ra (hay được dùng cho các máy có tính năng theo dõi và quan sát người dùng qua eye-tracking, vision-tracking).

Ngoài ra thư viện của thuật toán Boilerpipe còn đi kèm với các hỗ trợ trong việc cắt lấy thông tin từ website. Nó có thể lấy HTML từ web, trích xuất văn bản từ HTML rồi lọc lại thông tin cần thiết. Tính năng extractFromURL sẽ lấy thông tin từ URL rồi dùng Boilerpipe để lọc lấy các văn bản thông tin quan trọng dưới dạng string bằng dòng code ArticleExtractor sau:

Thư viện Boilerpipe cung cấp các trình rút trích khác nhau dựa trên thuật toán boilerpipe, với ‘ArticleExtractor’ được tối ưu hóa cụ thể cho các bài báo định dạng HTML. ‘ArticleExtractor’ tập trung cụ thể vào các thẻ HTML được sử dụng trong mỗi khối nội dung và mật độ liên kết đi. Nhờ đó mà hiệu quả cao hơn so với ‘DefaultExtractor’

Những tính năng built-in functions nói trên sẽ làm hết mọi việc cho ta:

  • HTMLFetcher.fetch    lấy các tài liệu HTML
  • getTextDocument    lọc lấy tài liệu chữ
  • CommonExtractors.ARTICLE_EXTRACTOR.getText    lọc lấy những thông tin cần thiết sử dụng thuật toán Boilerpipe

Sau đó để xuất và hiển thị kết quả thì bạn thêm dòng code vào main function:

Bạn sẽ thấy kết quả là chỉ có các text quan trọng, thuộc phần chính của bài báo, không có quảng cáo, các thẻ HTML và liên kết ngoài.

Part of Speech – POS tagger

Giờ thì bạn đã chiết xuất thành công phần thông tin chính từ một bài viết. Bước tiếp theo là xác định những đoạn nào là người dùng muốn xem hoặc thích đọc.

Có nhiều bạn sẽ muốn sử dụng string hoặc expression search để thực hiện công việc trên. Tuy vậy nó đi kèm với nhiều bất lợi.

Thứ nhất, string search đôi khi đưa ra kết quả sai (false positives) dù nó theo đúng yêu cầu. Cho dễ hiểu, thay vì kiếm một bài về Microsoft Excel thì nó lại kiếm một bài bất kì miễn là có chữ Microsoft

Hơn nữa, việc sử dụng regular expression search cũng không chính xác (false negative). Một ví dụ điển hình là bài viết với tựa đề “Microsoft phá sản” có thể bị bỏ qua chỉ vì bạn search chữ “ Microsoft “ với khoảng cách hai bên.

Cuối cùng, nếu người dùng muốn kiếm một lượng lớn các bài viết về nhiều công ty khác nhau thì việc searching cả một bài viết cho từng tên công ty là rất tốn thời gian cũng như performace cực kì thấp.

Stanford’s CoreNLP library chứa đựng nhiều tính năng mạnh mẽ và giải pháp để giải quyết cả 3 vấn đề trên.

Trong bài viết này, chúng ta sẽ sử dụng Parts-of-Speech (POS) tagger. Nói chính xác hơn, POS tagger sẽ giúp ta tìm kiếm những danh từ riêng trong bài viết và so sánh chúng với portfolio của người dùng nhằm xác định nội dung thông tin họ thích.

Nhờ vào công nghệ của NLP, độ chính xác của tagger sẽ tăng cao trong khi tỉ lệ false positive và negative sẽ giảm đi. Ngoài ra, số lượng text cần so sánh cũng sẽ cắt bớt đi rất nhiều bởi các danh từ chỉ chiếm một phần nhỏ trong một bài viết thông thường. Nhờ vậy mà thời gian searching cũng được rút ngắn đáng kể.

Stanford CoreNLP cung cấp một tagger rất tiện lợi là MaxentTagger với chức năng POS Tagging với chỉ một vài dòng code đơn giản:

tagger function, ‘tagPos’, lấy 1 string làm input và output là string chứa chữ, thông tin của string input nhưng được sửa lại cho chính xác dựa vào POS tagger.

Hãy là những người đầu tiên đăng ký vé Early Bird từ 01/04 – 15/04 với giá ưu đãi chỉ còn 150k

Xử lý các kết quả từ Tagged output thành Set hoàn chỉnh

Tới bước này thì cũng có nghĩa chúng ta đã tạo được các funtion khác nhau cho ứng dụng như download, lọc, lấy và tag thông tin từ một bài viết. Nhưng ta vẫn phải đảm bảo bài viết thật sự chính xác với những gì người dùng yêu cầu trong tìm kiếm.

Để làm được điều đó, chúng ta phải thu thập hết tất cả các danh từ riêng rồi kiểm tra dựa trên portfolio để xác định chúng.

Trước hết là việc lọc ra hết các danh từ, ta cần phải chia các tagged string output thành nhiều token (sử dụng space làm phân cách) rồi lại chia các token bằng ( _ )  và kiểm tra xem nếu từng đoạn có phải là danh từ riêng không.

Một khi đã có đủ danh từ riêng thì cần lưu trữ chúng dưới dạng data sao cho phù hợp với mục đích của chúng ta. Trong ví dụ của bài viết, ta sẽ sử dụng HashSet. HashSet giúp loại trừ việc entry bị lập cũng như không track được thứ tự của entry. Ngoài ra, việc truy vấn (membership queries) sẽ nhanh hơn.

Dưới đây là một funtion với mục đích chia và lưu trữ các danh từ riêng. Đặt funtion trong class PortfolioNewsAnalyzer của ứng dụng:

Tuy nhiên cách áp dụng này vẫn tồn tại một vấn đề. Nếu như thông tin có các danh từ riêng vốn là 2 danh từ riêng khác kết hợp vào thì funtion trên sẽ bỏ qua. Nói cách khác, nếu một hãng tên “Tom Hilander” thì nó sẽ bị chia thành 2 string khác nhau là “Tom” và “Hilander” thay vì string “Tom Hilander”.

Để giải quyết vấn đề trên, chúng ta cần thu thập cả các danh từ riêng liên tiếp. Như vậy funtion sau khi được update sẽ là như thế này:

So sánh giữa Portfolio và set danh từ riêng

Sau khi đã hoàn thành các bước trên, thì việc tiếp theo là so sánh HashSet với list thông tin mà người dùng muốn xem.

Bạn sẽ chỉ cần cho thêm dòng code sau vào class PortfolioNewsAnalyzer:

Kết hợp tất cả

Giờ thì bạn đã có những thứ cần thiết cho ứng dụng rồi đó – Lấy, lọc, tagging, thu thập và so sánh. Và ta cần một function để chạy nguyên cái app. Giờ bạn thêm dòng function sau vào PortfolioNewsAnalyzer:

Tạo ứng dụng thông minh (NLP App) không phải là chuyện khó như mọi người nghĩ

Trong bài viết này, chúng ta đã cùng tìm hiểu qua quá trình xây dựng một ứng dụng với tính năng tải một bài viết từ một URL, làm sạch nó bằng Boilerpipe, xử lý nó sử dụng Stanford NLP và kiểm tra nếu bài viết có thông tin người dùng muốn xem. Qua đó ta thấy được NLP giúp việc tạo ra những phần mềm thông minh một cách dễ dàng hơn.

Tôi hy vọng bài viết này sẽ giúp cho bạn hiểu được những khái niệm và kỹ thuật hữu ích trong việc xử lý ngôn ngữ tự nhiên và quan trọng hơn cả, tiếp thêm lửa đam mê cho các bạn lập trình muốn viết ra các ứng dụng thông minh.

Techtalk via Toptal

CHIA SẺ