HistogramPredictor.java revision c7c9cf164cc58d03156a53be35e58c3b75871a23
1d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build/*
2d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * Copyright (C) 2011 The Android Open Source Project
3d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build *
4d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * Licensed under the Apache License, Version 2.0 (the "License");
5d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * you may not use this file except in compliance with the License.
6d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * You may obtain a copy of the License at
7d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build *
8d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build *      http://www.apache.org/licenses/LICENSE-2.0
9d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build *
10d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * Unless required by applicable law or agreed to in writing, software
11d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * distributed under the License is distributed on an "AS IS" BASIS,
12d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * See the License for the specific language governing permissions and
14d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * limitations under the License.
15d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build */
16d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
17M��Q,_�w����
18d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildpackage android.bordeaux.learning;
19d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
20d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport android.util.Log;
21d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport android.util.Pair;
22d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
23WE�.�F�Y�H$T�import java.io.ByteArrayInputStream;
24d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.io.ByteArrayOutputStream;
25rX����g�Ă��A���M>��'�'|�����᰻���yimport java.io.IOException;
26d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.io.ObjectInputStream;
27d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.io.ObjectOutputStream;
28d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.io.Serializable;
29d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.ArrayList;
30d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.Collections;
31d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.Comparator;
32d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.HashMap;
33d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.HashSet;
34d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.Iterator;
35d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.List;
36d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.Map;
37d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildimport java.util.Map.Entry;
38d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
39d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
40d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build/**
41d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * A histogram based predictor which records co-occurrences of applations with a speficic feature,
42d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * for example, location, * time of day, etc. The histogram is kept in a two level hash table.
43d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build * The first level key is the feature value and the second level key is the app id.
44d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build */
45d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build// TODOS:
46d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build// 1. Use forgetting factor to downweight istances propotional to the time
47d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build// 2. Different features could have different weights on prediction scores.
48d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build// 3. Make prediction (on each feature) only when the histogram has collected
49d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build//    sufficient counts.
50d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-buildpublic class HistogramPredictor {
51d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    final static String TAG = "HistogramPredictor";
52t���Oo
53w.d�O��    private HashMap<String, HistogramCounter> mPredictor =
54d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            new HashMap<String, HistogramCounter>();
55d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
56d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    private static final double FEATURE_INACTIVE_LIKELIHOOD = 0.00000001;
57d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    private final double logInactive = Math.log(FEATURE_INACTIVE_LIKELIHOOD);
58w�~<l��
59d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
60OzJ�Ŵ>�G��Qz _B�r��]:k��.��׵:I�Qk�p'ׂvjQ����u�dtM     * This class keeps the histogram counts for each feature and provide the
61Yx^CHBp�O�     * joint probabilities of <feature, class>.
62x��^�C�N�e�l	��!���     */
639S}    private class HistogramCounter {
64d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        private HashMap<String, HashMap<String, Integer> > mCounter =
65d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                new HashMap<String, HashMap<String, Integer> >();
66d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        private int mTotalCount;
67d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
68d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        public HistogramCounter() {
69sw�Y��            resetCounter();
70d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
71d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
72d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        public void setCounter(HashMap<String, HashMap<String, Integer> > counter) {
73h��{������&��**�W}�x�l�L(�W�o��p�Lg*            resetCounter();
74B��f��z            mCounter.putAll(counter);
75d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
76d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            // get total count
77d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            for (Map.Entry<String, HashMap<String, Integer> > entry : counter.entrySet()) {
78d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                for (Integer value : entry.getValue().values()) {
79HMEG��                    mTotalCount += value.intValue();
80d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                }
81d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            }
82d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
83d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
840��        public void resetCounter() {
85d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            mCounter.clear();
86d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            mTotalCount = 0;
87d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
88c�d��
89d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        public void addSample(String className, String featureValue) {
90d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            HashMap<String, Integer> classCounts;
91d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
92d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            if (!mCounter.containsKey(featureValue)) {
93d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                classCounts = new HashMap<String, Integer>();
94d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                mCounter.put(featureValue, classCounts);
95d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            }
96d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            classCounts = mCounter.get(featureValue);
97d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
98d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            int count = (classCounts.containsKey(className)) ?
99d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    classCounts.get(className) + 1 : 1;
100d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            classCounts.put(className, count);
101d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            mTotalCount++;
102D0SI]���Lb�Lp�        }
103cXI�ti-
104d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        public HashMap<String, Double> getClassScores(String featureValue) {
105d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            HashMap<String, Double> classScores = new HashMap<String, Double>();
106d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
107d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            double logTotalCount = Math.log((double) mTotalCount);
108o�S<��,��J{�\'            if (mCounter.containsKey(featureValue)) {
109d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                for(Map.Entry<String, Integer> entry :
110d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                        mCounter.get(featureValue).entrySet()) {
111d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    double score =
112sf��PѰ��ʐ�XN�ve�?�����{�蛁�:���}p;p=�	���X������z*ΰB�w                            Math.log((double) entry.getValue()) - logTotalCount;
113d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    classScores.put(entry.getKey(), score);
114d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                }
115d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            }
116d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            return classScores;
117d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
118d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
119d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        public HashMap<String, HashMap<String, Integer> > getCounter() {
120d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            return mCounter;
121d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
122d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
123d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
124d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
125d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * Given a map of feature name -value pairs returns the mostly likely apps to
126d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * be launched with corresponding likelihoods.
127d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     */
128d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public List<Map.Entry<String, Double> > findTopClasses(Map<String, String> features, int topK) {
129m����� �� `)�B(�        // Most sophisticated function in this class
130YAYЌ=)#��bDF�R��X��ќ���n۔o[:wP�        HashMap<String, Double> appScores = new HashMap<String, Double>();
131d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        double defaultLikelihood = mPredictor.size() * logInactive;
132d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
133d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        // compute all app scores
134d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        for (Map.Entry<String, HistogramCounter> entry : mPredictor.entrySet()) {
135d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            String featureName = entry.getKey();
136d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            HistogramCounter counter = entry.getValue();
137d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
138d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            if (features.containsKey(featureName)) {
139d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                String featureValue = features.get(featureName);
140N;T֭�r��O�ś                HashMap<String, Double> scoreMap = counter.getClassScores(featureValue);
141d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
142d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                for (Map.Entry<String, Double> item : scoreMap.entrySet()) {
143d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    String appName = item.getKey();
144d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    double appScore = item.getValue();
145d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
146d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    double score = (appScores.containsKey(appName)) ?
147d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                        appScores.get(appName) : defaultLikelihood;
148d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    score += appScore - logInactive;
149d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
150d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    appScores.put(appName, score);
151d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                }
152d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            }
153d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
154d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
155d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        // sort app scores
156d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        List<Map.Entry<String, Double> > appList =
157d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build               new ArrayList<Map.Entry<String, Double> >(appScores.size());
158d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        appList.addAll(appScores.entrySet());
159n��        Collections.sort(appList, new  Comparator<Map.Entry<String, Double> >() {
160d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            public int compare(Map.Entry<String, Double> o1,
161d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                               Map.Entry<String, Double> o2) {
162d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                return o2.getValue().compareTo(o1.getValue());
1636i�            }
164T9g        });
165d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
166d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        Log.e(TAG, "findTopApps appList: " + appList);
167k�i�p��	��D        return appList;
168d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
169d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
170Kr4    /*
171d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * Add a new observation of given sample id and features to the histograms
172d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     */
173d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public void addSample(String sampleId, Map<String, String> features) {
174d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        for (Map.Entry<String, HistogramCounter> entry : mPredictor.entrySet()) {
175d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            String featureName = entry.getKey();
176d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            HistogramCounter counter = entry.getValue();
177d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
178M3�� TRP�            if (features.containsKey(featureName)) {
179d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                String featureValue = features.get(featureName);
180d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                counter.addSample(sampleId, featureValue);
181d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            }
182i���'        }
183d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
184d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
185d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
186d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * reset predictor to a empty model
187swQ��     */
188d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public void resetPredictor() {
189d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        // TODO: not sure this step would reduce memory waste
190d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        for (HistogramCounter counter : mPredictor.values()) {
191d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            counter.resetCounter();
192d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
193d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        mPredictor.clear();
194d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
195z�;p
196d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
197i�[}W*�oZ��&R��<<�#��b������A'F�n���     * specify a feature to used for prediction
198d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     */
199d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public void useFeature(String featureName) {
200d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        if (!mPredictor.containsKey(featureName)) {
201d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            mPredictor.put(featureName, new HistogramCounter());
202d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
203d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
204d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
205d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
206d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * convert the prediction model into a byte array
207d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     */
208d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public byte[] getModel() {
209d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        // TODO: convert model to a more memory efficient data structure.
210E��R��k�D�*�        HashMap<String, HashMap<String, HashMap<String, Integer > > > model =
211k��`�a��y�Xe;�W������NH]��BE��N�)�S                new HashMap<String, HashMap<String, HashMap<String, Integer > > >();
212a�zi��;.�m������������z.�b}�W        for(Map.Entry<String, HistogramCounter> entry : mPredictor.entrySet()) {
213d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            model.put(entry.getKey(), entry.getValue().getCounter());
214d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
215d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
216d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        try {
217d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
218d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
2191���� 	�r�X�DŽW�L��U�|��T�h�/�            objStream.writeObject(model);
220d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            byte[] bytes = byteStream.toByteArray();
221d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            //Log.i(TAG, "getModel: " + bytes);
222d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            return bytes;
223d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        } catch (IOException e) {
224d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            throw new RuntimeException("Can't get model");
225d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
226d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
227d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
228d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    /*
229d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build     * set the prediction model from a model data in the format of byte array
2302'�|��ce�TZpc��&k<     */
231d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    public boolean setModel(final byte[] modelData) {
232d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        HashMap<String, HashMap<String, HashMap<String, Integer > > > model;
233d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
234d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        try {
235d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            ByteArrayInputStream input = new ByteArrayInputStream(modelData);
236d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            ObjectInputStream objStream = new ObjectInputStream(input);
237d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            model = (HashMap<String, HashMap<String, HashMap<String, Integer > > >)
238d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                    objStream.readObject();
239d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        } catch (IOException e) {
240d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            throw new RuntimeException("Can't load model");
241d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        } catch (ClassNotFoundException e) {
242d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            throw new RuntimeException("Learning class not found");
243d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
244d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build
245d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        resetPredictor();
246d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        for (Map.Entry<String, HashMap<String, HashMap<String, Integer> > > entry :
247d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build                model.entrySet()) {
248d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            useFeature(entry.getKey());
249d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build            mPredictor.get(entry.getKey()).setCounter(entry.getValue());
250d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        }
251d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build        return true;
252d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build    }
253pF@�ؤ?sH�\�YZ�U�\���[��:}
254d1f1aaf649cac3788a261a5380448579f54b5dcandroid-devtools-build