طبقه بندی متون- سکو

سرویس: طبقه بندی متون | Text Classifier

تعریف مسئله

هدف از این مسئله، دسته بندی خودکار متون خبری در موضوع های از پیش تعریف شده است. برای مثال می خواهیم بفهمیم که نوع خبرهای مختلف روی دسته های از قبل تعریف شده ورزشی، سیاسی، اقتصادی، اجتماعی چیست.

چگونه کار میکند

برای این مسئله دو سطح ریزدانگی متفاوت، مورد استفاده قرار گرفته است. سطح درشت دانه،‌شامل ۶ موضوع و سطح ریزدانه شامل ۴۱ موضوع است. موضوعاتی مانند سیاست، ورزش، فرهنگ و هنر و غیره در حالت درشت دانه و موضوعاتی مانند دولت، فوتبال، موسیقی و غیره در حالت ریزدانه معرفی شده اند. فهرست کامل عناوین این موضوعات در لینک قرار دارند.

الگوریتم

یادگیری عمیق؟ چرا که نه. ما برای پیاده سازی این سرویس از روش‌های مبتنی بر یادگیری عمیق استفاده کرده‌ایم. قبل از یادگیری عمیق، برای حل این مسئله، ابتدا ویژگی های شهودی متفاوتی به دست می آمد. در مرحله بعد یه دسته‌بند، مانند svm یا max_entropy روی آن ویژگی ها تعریف می کردند تا عمل دسته بندی را انجام دهند. معمولا به دست آوردن این ویژگی ها نیازمند منابع متعدد مانند فارس نت، یا پارسرها هستند که به دلیل sparsity و ناقص بودن همیشگی این منابع، این عمل را با خطا و هزینه زیادی همراه می کنند. از قدیم، این رویا که بتوان بدون تعریف ویژگی و بر روی داده خام، مدل را آموزش داد، مطرح بوده است. یادگیری عمیق با تعریف سطوح مختلف انتزاعی در لایه های متوالی، این رویا را محقق کرده است. نمایش برداری کلمات در یادگیری عمیق، برای آموزش مدل از شبکه های عصبی استفاده می شود. در این مدل ها باید متن را در قالب بردارهایی از اعداد حقیقی، به مدل ورودی بدهیم. یک راه برای تبدیل هر کلمه به بردار، استفاده از نمایش one hot آن است. در این روش، هر کلمه را در قالب برداری با طول تعداد کلمات منحصر به فرد کل پیکره، نمایش می‌دهند که هر بعد از آن، متناظر با یک کلمه است. در نمایش برداری یک کلمه مشخص، به این روش، بعد مربوط به آن کلمه ۱ و سایر ابعاد ۰ است. این نحوه نمایش، سبب می شود تا بردارهای کلمات مختلف بر هم عمود شده و هیچ رابطه‌ای بین آن‌ها وجود نداشته باشد. همچنین با افزایش sparsity، در این حالت generalization مدل به شدت کاهش پیدا می کند. در سال ۲۰۱۳ میکولو، در مقاله ای، روش word2vec را برای نمایش برداری کلمات معرفی کرد. در این روش هر کلمه با یک بردار به طول مشخص(مثلا ۳۰۰) نشان داده می شود. در این روش کلماتی که context مشابهی دارند، بردارهای نزدیک به یکدیگر دارند. میکولو نشان داد که نمایش کلمات در این بردارها، می تواند مفهوم هر کلمه را در سطوح مختلف معنایی و نحوی مشخص کند. این کار نقطه عطفی در استفاده از روش‌های مبتنی بر یادگیری عمیق در پردازش زبان طبیعی بود . پس از word2vec روشهای دیگری مانند glove و fasttext نیز معرفی شدند. روش glove به دلیل استفاده از قواعد آماری، معمولا عملکرد بهتری را نسبت به سایر روش ها دارد. به همین منظور در این پژوهش از این روش استفاده شده است. ما الگوریتم glove را روی ۳۷ میلیون خبر نرمال شده (حدود ۱۵۰ گیگابایت)، آموزش دادیم و هر کلمه را در قالب یک بردار با طول ثابت نمایش دادیم. استفاده از یادگیری عمیق پس از نمایش کلمات، در بردارهای مشخص، باید آن ها را به یک مدل یادگیری عمیق ورودی دهیم. معمولا شبکه های CNN و LSTM برای این منظور، مورد استفاده قرار می گیرند. به طور خلاصه این شبکه ها با ورودی گرفتن بردارهای کلمات، سعی میکنند تا به یک representation برای متن ورودی برسند، این دو روش به دلیل استفاده از parameter sharing می توانند ورودی های با طول متغیر مانند متن را پردازش کنند. شبکه های CNN ابتدا در مسائل بینایی ماشین،‌مورد استفاده قرار گرفتند و پس از ورودی یادگیری عمیق به پردازش زبان، ابتدا در این مسائل نیز مورد استفاده قرار گرفتند. این شبکه ها با تعریف کرنل های با پهنای متفاوت می توانند ویژگی های مختلف را از بردارهای کلمات استخراج کنند. کرن لهای با طول متفاوت، نقش ان‌گرام ها را در پردازش زبان، ایفا می‌کنند. شبکه های LSTM برای مسائل برچسب زنی دنباله‌ها به وجود آمده اند و بر خلاف شبکه‌های CNN می توانند وابستگی های طولانی مدت را نیز به صورت پویا، مدیریت کنند. به طور کلی عملکرد LSTMها در پردازش متن، بهتر است ولی در جایی که تنها وابستگی های محلی کافی هستند، شبکه های CNN به دلیل سرعت بالاتر آموزش و تست بهتر خواهند بود. در این سرویس، ما از شبکه‌های LSTM به عنوان واحد اصلی کار استفاده کرده ایم. مشکلات LSTM معمولا متن‌های خبری،‌ طولانی هستند و اندازه آن‌ها بیشتر از یک یا دو جمله است. در تئوری LSTM می‌تواند وابستگی‌های طولانی مدت را هر اندازه که باشند مدیریت کند ولی در عمل این اتفاق نمی‌افتد و برای متن‌های طولانی، پس از مدتی شاهد ناپدید شدن گرادیان هستیم. روش‌های مختلفی از مکانیزم‌هایی مانند self attention برای حل این مشکل استفاده کرده‌اند ولی این روش‌ها نیز نمی‌توانند به صورت موثر، این مشکل را حل کنند. به عبارت دیگر باید با تغییرات ساختاری در معماری عمیق، این چالش را برطرف کرد. روش ما در روش ما سعی کرده‌ایم تا از ساختار متون خبری استفاده کنیم. هر متن از چندین جمله تشکیل شده است که معنای هر جمله می‌تواند به صورت مستقل به دست بیاید. ما از همین ساختار استفاده کرده ایم. به عبارت دیگر ما به صورت مستقل، representation هر جمله را به دست می‌آوریم و در بخش بعد با ترکیب آن‌ها به representation کل متن می‌رسیم. در این روش، ابتدا متن را بر اساس جملات آن tokenize می شود. در مرحله بعد هر جمله را به یک LSTM دو طرفه با وزن های یکسان داده می شود چرا که ترتیب کلمات در یک جمله اهمیت دارد و می‌تواند معنی کلمات را مشخص کند. برای مثال کلمه جوان در عبارت‌های «باشگاه خبرنگاران جوان» و «جوان ایرانی» مفاهیم متفاوتی را از خود نشان می‌دهد که این موضوع در به دست آوردن نمایش نهایی جمله اهمیت دارد. این در حالی است که ترتیب جملات در متن برای تعیین موضوع نهایی متن، اهمیت چندانی ندارد. به عبارت دیگر با جا‌به‌جایی جملات در یک متن، باز هم می توان با همان دقت قبلی، موضوع متن را تشخیص داد. برای افزایش سرعت در آموزش و همچنین افزایش Generalization مدل، برای به دست آوردن نمایش نهایی متن از max pooling استفاده کردیم. این کار هم باعث افزایش دقت(به خاطر افزایش generaliztion) و هم افزایش چشم گیر سرعت یادگیری و تست شده است. با این کار در هر بعد به دست آمده از جملات، مقدار بیشینه را در آن بعد، محاسبه کرده و به عنوان مقدار نهایی آن بعد محاسبه می کنیم. با این کار به یک بردار به طول ثابت می رسیم که representation کل متن را مشخص می کند. در نهایت پس از گذر از دو لایه fully connected که نورون های لایه انتهایی به اندازه تعداد کلاس های تعریف شده است و همچنین اعمال تابع softmax احتمال وقوع هر کلاس به دست می آید. همچنین برای آموزش از تابع هزینه cross entropy استفاده شده است. در ضمن، از dropout در تمامی لایه‌ها برای جلوگیری از overfit شدن مدل استفاده شده است.

دیتای مورد استفاده

برای ساخت مجموعه داده، از هر دسته ریز دانه، ۱۰۰۰ خبر و در مجموع ۴۱۰۰۰ خبر برداشتیم. پس از جا به جایی تصادفی نمونه‌ها، ۸۰ درصد از آن‌ها را به عنوان داده آموزش، ۱۰ درصد را به عنوان داده ارزیابی و ۱۰ درصد باقی مانده را به عنوان داده تست، مشخص کردیم. برای حالت ۶ کلاسه نیز دقیقا از همین مجموعه داده استفاده کردیم با این تفاوت که برچسب‌های به دست آمده از مجموعه داده را به برچسب معادلشان در حالت درشت دانه، تبدیل کردیم.

کاربرد سرویس

این سرویس، می‌تواند پاسخگوی چالش‌های بسیاری باشد. سیستمی را در نظر بگیرید که در آن کاربران با سلایق متفاوت به دنبال خبرهای مورد نظرشان هستند. یک کاربر علاقه دارد تا خبرهای مرتبط با موسیقی را دنبال کند، کاربر دیگر علاقه‌مند به بررسی خبرهای بورس است و یک کاربر دیگر فقط می‌خواهد خبرهای فوتبالی را مشاهده کند. این سرویس می‌تواند با دسته بندی خبرها به این موضوعات، این چالش را به راحتی برطرف کند. علاوه بر این، این سرویس می‌تواند مدل رفتاری نویسندگان را مشخص کند. برای مثال یک نویسنده بیشتر مطالب سیاسی را کار می‌کند و یک نویسنده دیگر، روی مطالب ورزشی تخصص دارد. همچنین این سرویس می‌تواند به مدل کردن رفتار جوامع و گروه‌های گوناگون بر اساس مطالب منتشر شده آن‌ها کمک کند.

نحوه استفاده

شما باید از طریق متود Post خبرهای مورد نظرتان را در قالب یک فایل json ارسال کنید و بر اساس پارامترهایی که تعریف کرده اید خروجی مورد نظرتان را دریافت کنید.

ورودی API

برای مثال پارامترهای زیر را در نظر بگیرید: querystring = {"decode_on" : "both", "result_type" : "best_label"} برای این پارامترها، ورودی زیر از طریق متود Post ارسال شده‌اند: {"text": [ "حسن روحانی رئیس جمهور ایران است." ] }

خروجی API

برای این ورودی و پارامترهای داده شده، خروجی زیر داده خواهد شد: [ [ "سیاست", "دولت" ] ]

نمونه کد PHP

                                        $ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://sakoo.dataak.com/api/services/nlp/text_classifier");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
 $data = [
     
    'text'=>'روحیه تیمی در دیتاک از نان شب هم واجب‌تر است و افرادی که توانایی کار تیمی ندارند در کنار ما آرامش خود را از دست خواهند داد',
    'decode_on'=>6,
    'result_type'=>'best_label',
    'token'=> 'token'
 ];          
 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
 $server_output = curl_exec($ch);
 print_r($server_output);
                                    

نمونه کد java

                                        import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

    public class MTest {

        public static void main(String[] args) throws Exception{
            URL url = new URL("https://sakoo.dataak.com/api/services/nlp/text_classifier");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            Map<String, String> parameters = new HashMap<>();
            con.setDoOutput(true);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setConnectTimeout(5000);
            con.setReadTimeout(5000);
            con.setInstanceFollowRedirects(false);
            
            String token="token";
            token=java.net.URLEncoder.encode(token, "UTF-8").replace("+","%20");
            
            String urlParameters  = "text=روحیه تیمی در دیتاک از نان شب هم واجب‌تر است و افرادی که توانایی کار تیمی ندارند در کنار ما آرامش خود را از دست خواهند&decode_on=6&result_type=best_label&token="+token;
            try(OutputStream os = con.getOutputStream()) {
                byte[] input = urlParameters.getBytes("utf-8");
                os.write(input, 0, input.length);
            }
            
            DataOutputStream out = new DataOutputStream(con.getOutputStream());
            out.flush();
            out.close();

            int status = con.getResponseCode();
            String s=con.getResponseMessage();
            Reader streamReader = null;
            
            if (status > 299) {
               
                streamReader = new InputStreamReader(con.getErrorStream());
            } else {
                streamReader = new InputStreamReader(con.getInputStream());

                BufferedReader in = new BufferedReader(
                        new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuffer content = new StringBuffer();
                while ((inputLine = in.readLine()) != null) {
                    content.append(inputLine);
                }
                in.close();
                
                System.out.println(content);
            }
            con.disconnect();
        }
    }
                                    

نمونه کد python

                                        import requests
url = 'https://sakoo.dataak.com/api/services/nlp/text_classifier'
data = {
    'text': 'روحیه تیمی در دیتاک از نان شب هم واجب‌تر است و افرادی که توانایی کار تیمی ندارند در کنار ما آرامش خود را از دست خواهند داد.',
    'decode_on':6,
    'result_type':'best_label',
    'token':'token'

}
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.3'}
response = requests.post(url, data=data, headers=headers)

print(response.text)