Showing posts with label machine learning. Show all posts
Showing posts with label machine learning. Show all posts

Saturday, May 5, 2018

AI for lip reading

It is exciting to push your imagination for where else can you apply AI, machine learning and most certainly -- deep learning, that is so popular these days. I came across this question on quora that provoked me to think a bit how would one go about training a neural network to lip read. I don't actually know what made me answer this question more: that found myself in an unusual context sitting on an Angularjs meetup at Google offices in New York City (after work, usual level tired) or the question itself. Whatever the reason, here is my answer:

Source: http://theconversation.com/our-lip-reading-technology-promises-to-make-hearing-aids-more-human-45166

I would probably first start with formalizing what is lip reading process from a human understandable algorithm point of view. May be it is worth to talk to a professional, like a spy or something. Obviously you need training data. Understanding, what is lip reading from the algorithm perspective will affect on what data you need.


    1. To read a word of several syllables you’d need a sequence of anchor lip positions, that represent syllables. Or probably vowels / consonants. See, I don’t know, which one is best. But you’d need to start with the lowest level possible out of which you can compose larger sequences, like letters -> syllables -> words. Let’s call these states.
    2. A particular lip posture (is that the right word?) will most probably map to ambiguous states.
    3. Now the interesting part is how to resolve the ambiguities. Number 2 produces several options. Out of these you can produce a multitude of words that we can call candidates.
    4. Then you need to score candidates based on some local context information. Here it turns into a natural language understanding.
    5. I'd start with seq2seq.

    Wednesday, November 1, 2017

    Will deep learning make other machine learning algorithms obsolete?

    The fourth (fifth?) quoranswer is here! This time we'll talk a bit about deep learning and its role in making other state of the art machine learning methods obsolete.


    Will deep learning make other machine learning algorithms obsolete?


    I will try to take a look at the question from the natural language processing perspective.

    There is a class of problems in NLProc, that might not be benefited from deep learning (DL), at least directly. For the same reasons, machine learning  (ML) cannot help so easily. I will give three examples, which share more or less the same property so hard to model with ML or DL:

    1. Identifying and analyzing a sentiment polarity oriented towards a particular object: person, brand etc. Example: I like phoneX, but dislike phoneY. If you monitor the sentiment situation for the phoneX you'll expect this message to be positive, while negative polarity for the phoneY. One can argue, it is easy / doable with ML / DL, but I doubt you can stay solely within that framework. Most probably you'll need a hybrid with rule-based system, syntactic parsing etc, which somewhat defeats the purpose of DL: be able to train neural network on a large amount of data without domain (linguist) knowledge.

    2. Anaphora resolution. There are systems that use ML (and hence DL can be tried?), like BART coreference system , but most of the research I have seen so far is based around some sort of rules / syntactic parsing (this presentation is quite useful: Anaphora resolution). There is a vast application area for AR, including sentiment analysis and machine translation (also fact extraction, question-answering etc).

    3. Machine translation. Disambiguation, anaphora, object relations, syntax, semantics and more in a single soup. Surely, you can try to model all of these with ML, but commercial systems in MT are more or less done with rules (+ml recently). I'm expecting DL can produce advancements in MT. I'll cite one paper here that uses DL and improves on phrase-based SMT: [1409.3215] Sequence to Sequence Learning with Neural Networks Update: some recent fun experiment with DL based machine translation.

    The list can be extended to knowledge bases etc, but I hope I made my point.

    Sunday, April 27, 2014

    Weka template project for sentiment classification of an English text

    Internet is buzzing about machine learning. Many folks use it for fun and profit

    credits: Customers Who Bought This Item Also Bought PaulsHealthBlog.com, 11.04.2014

    But! When a non-expert gets around started with these topics in practice, it becomes increasingly difficult to just get going. There are of course quick solutions, like scikit-learn library for Python. If you are a Java developer, there are a few options as well: Weka, Apache Mahout. Both of these are generic enough to be applied to different machine learning problems, including text classification. More tailored libraries and packages for text oriented machine learning in Java are Mallet and Stanford's set of libraries. There are as well some less known machine learning toolkits, like Java-ML.

    This post will focus on Weka and will give you a very simple and working template project for classifying sentiment in the English text. Specifically, we will create three way sentiment classifier using Multinomial Naive Bayes algorithm.

    In my view, there are three main practical problems, that a programmer seeks to find solutions for using a machine learning library: setting up a classifier algorithm, adding training instances (effectively, training the classifier) and I/O (storing and retrieving a model). Beyond this and of high importance is measuring the quality of the trained model that we will take a look at as well.

    Setting up a classifier

    As mentioned above, we will use the Multinomial Naive Bayes algorithm. To get going, let's set it up for the three way sentiment classification:


    public class ThreeWayMNBTrainer {
        private NaiveBayesMultinomialText classifier;
        private String modelFile;
        private Instances dataRaw;
    
        public ThreeWayMNBTrainer(String outputModel) {
            // create the classifier
            classifier = new NaiveBayesMultinomialText();
            // filename for outputting the trained model
            modelFile = outputModel;
    
            // listing class labels
            ArrayList<attribute> atts = new ArrayList<attribute>(2);
            ArrayList<string> classVal = new ArrayList<string>();
            classVal.add(SentimentClass.ThreeWayClazz.NEGATIVE.name());
            classVal.add(SentimentClass.ThreeWayClazz.POSITIVE.name());
            atts.add(new Attribute("content",(ArrayList<string>)null));
            atts.add(new Attribute("@@class@@",classVal));
            // create the instances data structure
            dataRaw = new Instances("TrainingInstances",atts,10);
        }
    
    }
    

    What goes in the above code is:
    • Create the classifier
    • List the target labels: NEGATIVE and POSITIVE
    • Create the instances data structure
    In a similar fashion, but with more classes (target labels) we'd set up a five way classifier, using the same algorithm under the hood:

    public class FiveWayMNBTrainer {
        private NaiveBayesMultinomialText classifier;
        private String modelFile;
        private Instances dataRaw;
    
        public FiveWayMNBTrainer(String outputModel) {
            classifier = new NaiveBayesMultinomialText();
            classifier.setLowercaseTokens(true);
            classifier.setUseWordFrequencies(true);
    
            modelFile = outputModel;
    
            ArrayList<Attribute> atts = new ArrayList<Attribute>(2);
            ArrayList<String> classVal = new ArrayList<String>();
            classVal.add(SentimentClass.FiveWayClazz.NEGATIVE.name());
            classVal.add(SentimentClass.FiveWayClazz.SOMEWHAT_NEGATIVE.name());
            classVal.add(SentimentClass.FiveWayClazz.NEUTRAL.name());
            classVal.add(SentimentClass.FiveWayClazz.SOMEWHAT_POSITIVE.name());
            classVal.add(SentimentClass.FiveWayClazz.POSITIVE.name());
            atts.add(new Attribute("content",(ArrayList<String>)null));
            atts.add(new Attribute("@@class@@",classVal));
    
            dataRaw = new Instances("TrainingInstances",atts,10);
        }
    }
    

    Adding training instances (training a classifier)

    Training the classifier is the process of showing examples to the algorithm. An example usually consists of a set of pairs (x,y), where x is a feature vector and y is a label for this vector. In the context of sentiment analysis specifically, a feature vector can be words (unigrams) in a sentence and a label is sentiment: NEGATIVE, NEUTRAL or POSITIVE in the case of three way sentiment classification. The algorithm is expected to learn from the example set and generalize to predict labels y' for the previously unseen vectors x'.

    Engineering the features is both the mix of art and mechanical work, as I've once mentioned. And also finding good classifier options can be a task for statistical analysis with visualization.

    Let's implement the method for adding the training instances for three way classification:

    public void addTrainingInstance(SentimentClass.ThreeWayClazz threeWayClazz, String[] words) {
            double[] instanceValue = new double[dataRaw.numAttributes()];
            instanceValue[0] = dataRaw.attribute(0).addStringValue(Join.join(" ", words));
            instanceValue[1] = threeWayClazz.ordinal();
            dataRaw.add(new DenseInstance(1.0, instanceValue));
            dataRaw.setClassIndex(1);
        }
    

    So basically we put input unigrams (words) as a String x value and integer of label as y value, thus forming a training instance for the algorithm. Next the algorithm will internally tokenize the input string sequence and update the necessary probabilities.

    For five way classification the above method looks almost the same, except the first parameter is of type SentimentClass.FiveWayClazz.

    Training the model after we have finished adding the training examples is quite simple:

    public void trainModel() throws Exception {
            classifier.buildClassifier(dataRaw);
        }

    That's it!

    I/O (storing and retrieving the trained model)

    It is ok to train a model and classify right a way. But, that does not work, if you want to develop your model and ship that to production. In production mode your trained classifier will do its main work: classify new instances. So your model must be pre-trained and exist on disk. Storing and loading a trained model with Weka is extremely easy. This is thanks to the fact the classifiers extend abstract class AbstractClassifier, which in turn implements Serializable interface among others.

    Storing the trained model is as easy as:

    public void saveModel() throws Exception {
            weka.core.SerializationHelper.write(modelFile, classifier);
        }
    

    And loading the model is easy too:
    public void loadModel(String _modelFile) throws Exception {
            NaiveBayesMultinomialText classifier = (NaiveBayesMultinomialText) weka.core.SerializationHelper.read(_modelFile);
            this.classifier = classifier;
        }
    


    After we have loaded the model, let's classify some texts. The method for the three way classification is:

    public SentimentClass.ThreeWayClazz classify(String sentence) throws Exception {
            double[] instanceValue = new double[dataRaw.numAttributes()];
            instanceValue[0] = dataRaw.attribute(0).addStringValue(sentence);
    
            Instance toClassify = new DenseInstance(1.0, instanceValue);
            dataRaw.setClassIndex(1);
            toClassify.setDataset(dataRaw);
    
            double prediction = this.classifier.classifyInstance(toClassify);
    
            double distribution[] = this.classifier.distributionForInstance(toClassify);
            if (distribution[0] != distribution[1])
                return SentimentClass.ThreeWayClazz.values()[(int)prediction];
            else
                return SentimentClass.ThreeWayClazz.NEUTRAL;
        }
    

    Notice the line #12. Remember, that we have defined the target classes for the three way classifier as {NEGATIVE, POSITIVE}. So in principle our classifier should be capable to do the binary classification. But! In the event when the probability distribution between the classes is exactly equal, we can safely assume it is NEUTRAL class. So we get the three way classifier. The following test case should ideally pass:

    @org.junit.Test
        public void testArbitraryTextPositive() throws Exception {
            threeWayMnbTrainer.loadModel(modelFile);
            Assert.assertEquals(SentimentClass.ThreeWayClazz.POSITIVE, threeWayMnbTrainer.classify("I like this weather"));
        }
    

    Neat!

    To wrap things up, here is the "runner" class that builds the three-way classifier, saves the model and tests it for quality over the training data:

    public class ThreeWayMNBTrainerRunner {
        public static void main(String[] args) throws Exception {
            KaggleCSVReader kaggleCSVReader = new KaggleCSVReader();
            kaggleCSVReader.readKaggleCSV("kaggle/train.tsv");
            KaggleCSVReader.CSVInstanceThreeWay csvInstanceThreeWay;
    
            String outputModel = "models/three-way-sentiment-mnb.model";
    
            ThreeWayMNBTrainer threeWayMNBTrainer = new ThreeWayMNBTrainer(outputModel);
    
            System.out.println("Adding training instances");
            int addedNum = 0;
            while ((csvInstanceThreeWay = kaggleCSVReader.next()) != null) {
                if (csvInstanceThreeWay.isValidInstance) {
                    threeWayMNBTrainer.addTrainingInstance(csvInstanceThreeWay.sentiment, csvInstanceThreeWay.phrase.split("\\s+"));
                    addedNum++;
                }
            }
    
            kaggleCSVReader.close();
    
            System.out.println("Added " + addedNum + " instances");
    
            System.out.println("Training and saving Model");
            threeWayMNBTrainer.trainModel();
            threeWayMNBTrainer.saveModel();
    
            System.out.println("Testing model");
            threeWayMNBTrainer.testModel();
        }
    }
    
    


    The quality of the model

    Testing the trained model is fairly easy with Weka as well. Knowing the quality of your model is important because you want to make sure that there is no under- or overfitting happening. Underfitting means you haven't found an optimum of features describing your fenomena to fully utilize your training data, thus the model is long-sighted or too simple. Overfitting means you deal with over-learning your training data and over-adjusting for it, i.e. the model does not generalize for real world instances and becomes too short-sighted or too complex.

    There are different ways to test the model, one is use part of you training data as test data (for example one third) and perform N fold cross-validation. I.e. on each iteration take a new piece of training data for test data and compute sensible metrics, like precision / recall / accuracy etc. In the end of the cross-validation take average over computed values. This will be your "amortized" quality.

    We can also take a peek look at the quality by just counting the number of correctly classified instances from the training data:

        public void testModel() throws Exception {
            Evaluation eTest = new Evaluation(dataRaw);
            eTest.evaluateModel(classifier, dataRaw);
            String strSummary = eTest.toSummaryString();
            System.out.println(strSummary);
        }
    

    The method outputs the following statistics:

    Correctly Classified Instances       28625               83.3455 %
    Incorrectly Classified Instances      5720               16.6545 %
    Kappa statistic                          0.4643
    Mean absolute error                      0.2354
    Root mean squared error                  0.3555
    Relative absolute error                 71.991  %
    Root relative squared error             87.9228 %
    Coverage of cases (0.95 level)          97.7697 %
    Mean rel. region size (0.95 level)      83.3426 %
    Total Number of Instances            34345     
    

    The code can be found on my github. It utilizes the data posted on kaggle. So if you want to use the code as is (and perhaps even make a submission) you need to accept the terms of the kaggle competition and download the training set. I leave the exercise of implementing the full code for five-way classification and code for classifying kaggle's test set to the reader.



    Sunday, November 24, 2013

    Training on NLProc and Machine Learning

    Just did a training on NLProc (imho, better abbreviation for natural language processing than NLP) and Machine Learning for OK.ru (Russian Facebook owned by Mail.Ru Group) in person in Saint-Petersburg, Russia.

    OK.ru has a nice office not far from Petrogradskaya subway station in Saint-Petersburg (the central office is in Moscow).


    If you feel like your project is somewhat stuck and needs a fresh look or you need to widen you knowledge in NLProc and / or machine learning, feel free to contact me on g+. At the moment folks at SemanticAnalyzer can do this in Europe / western part of Russia. At SemanticAnalyzer we also offer a full package of services for natural language processing development in case there isn't expertise in your house. This includes project scoping, breaking down by technical tasks, time estimation, development, testing / evaluation and delivery.

    Sunday, August 25, 2013

    Машинное обучение без учителя для определения смысла слов: open source инструмент от Google word2vec

    Кросспост моего поста с http://mathlingvo.ru/

    В блоге Google Open Source Blog появилось сообщение о новом open source инструменте word2vec. Исследователи Google утверждают, что при его помощи можно получить смысл слов, лишь прочитав огромные массивы данных. Инструмент применяет "распределённые представления" текстовых данных для обнаружения связей между концептами -- и всё это при помощи машинного обучения без учителя (unsupervised machine learning) на основе нейронных сетей (neural networks).
    Интересно, что модель помещает близкие страны рядом, как и близкие столицы. Похожие связи возникают автоматически во время тренировки алгоритма.
    У исходного кода хорошая лицензия: Apache License 2.0, которая позволяет менять его без опубликования изменений и встраивать его в том числе в коммерческие приложения.
    В статье также упоминается ставший популярным в последнее время метод Deep Learning, дающий результаты, лучшие на порядок предыдущих методов. Кстати, большинство победителей конкурсов по машинному обучению на kaggle (ваш покорный слуга также имел честь участвовать) применяет либо ансамбли методов на Decision Trees, либо методы Deep Learning.
    // ./demo_word.sh
    Enter word or sentence (EXIT to break): machine translation
    
    Word: machine  Position in vocabulary: 799
    
    Word: translation  Position in vocabulary: 1206
    
              Word       Cosine distance
    ------------------------------------------------------------------------
              mmix              0.485542
        translator              0.484659
              msil              0.483476
            manual              0.479708
            turing              0.462978
      introduction              0.458771
          readable              0.449272
        unabridged              0.448343
          machines              0.447570
           rosetta              0.443270
          compiler              0.438949
        dictionary              0.437040
      translations              0.436334
        translated              0.429008
     specification              0.422286
        typewriter              0.422246
               awk              0.420415
           version              0.417623
       interpreter              0.415583
            itrans              0.414944
             tools              0.413505
         annotated              0.413150
            lincos              0.411448
          abridged              0.411152
              text              0.407197
          language              0.404664
            freedb              0.403896
           vulgate              0.402863
             xpath              0.401687
        calculator              0.397689
            enigma              0.394239
           klingon              0.394041
           opencyc              0.393687
           systran              0.391636
           multics              0.391623
               kli              0.389196
               apl              0.386948
          editions              0.383799
            skybox              0.383791
             algol              0.383730
    Enter word or sentence (EXIT to break): weather
    
    Word: weather  Position in vocabulary: 2693
    
              Word       Cosine distance
    ------------------------------------------------------------------------
              warm              0.634004
          humidity              0.611526
             humid              0.605240
           summers              0.594220
     thunderstorms              0.591256
          snowfall              0.590065
     precipitation              0.582246
           climate              0.580110
           winters              0.577238
          rainfall              0.570583
             rainy              0.566492
    below_freezing              0.566140
      rainy_season              0.561857
            cooler              0.558795
             winds              0.558283
            colder              0.557494
      cold_winters              0.545980
               wet              0.545650
            frosts              0.539969
             drier              0.539645
          climatic              0.537766
            warmer              0.535417
            winter              0.532653
      warm_summers              0.530857
             el_ni              0.530692
      temperatures              0.528191
    relative_humidity           0.527605
            summer              0.527042
      mild_winters              0.526249
           monsoon              0.524260
       trade_winds              0.523211
           daytime              0.523093
          seasonal              0.520377
               dry              0.519703
        hurricanes              0.517527
         subarctic              0.514771
        visibility              0.514740
         snowfalls              0.513660
         monsoonal              0.513538
       hot_summers              0.513050