В нашей прошлой статье мы говорим о косинусном подобии. Теперь мы собираемся реализовать это в Ember.js. Если вы не слышали об этом, это веб-фреймворк JavaScript с открытым исходным кодом, основанный на шаблоне Model-view-viewmodel (MVVM). Это позволяет разработчикам создавать масштабируемые одностраничные веб-приложения, включая в структуру общие идиомы и лучшие практики.
Давайте начнем !
Давайте создадим FAQ с именем модели, который имеет свойство вопросов и ответов, используя ember cli.
$ ember g model faq question:string answer:string
Давайте изменим нашу модель и используем данные фикстуры.
import DS from 'ember-data'; let faq = = DS.Model.extend({ question: DS.attr('string'), answer: DS.attr('string') }); faq.reopenClass({ FIXTURES: [ { id:1, question: 'How to log in ?', answer:'provide your username and password and click login' }, { id:2, question:'How to Reset Password?', answer:'Click on the “Forgot password?” ' } ] }); export default faq;
Далее нам нужно написать код, который вычисляет косинусное сходство. Здесь мы вычисляем косинусное сходство. Вы можете сохранить его как cosine-sim.js в файле utils.
function termFreqMap(str) { var words = str.split(' '); var termFreq = {}; words.forEach(function(w) { termFreq[w] = (termFreq[w] || 0) + 1; }); return termFreq; } function addKeysToDict(map, dict) { for (var key in map) { dict[key] = true; } } function termFreqMapToVector(map, dict) { var termFreqVector = []; for (var term in dict) { termFreqVector.push(map[term] || 0); } return termFreqVector; } function vecDotProduct(vecA, vecB) { var product = 0; for (var i = 0; i < vecA.length; i++) { product += vecA[i] * vecB[i]; } return product; } function vecMagnitude(vec) { var sum = 0; for (var i = 0; i < vec.length; i++) { sum += vec[i] * vec[i]; } return Math.sqrt(sum); } function cosineSimilarity(vecA, vecB) { return vecDotProduct(vecA, vecB) / (vecMagnitude(vecA) * vecMagnitude(vecB)); } export default function cosineSim(strA, strB) { var termFreqA = termFreqMap(strA); var termFreqB = termFreqMap(strB); var dict = {}; addKeysToDict(termFreqA, dict); addKeysToDict(termFreqB, dict); var termFreqVecA = termFreqMapToVector(termFreqA, dict); var termFreqVecB = termFreqMapToVector(termFreqB, dict); return cosineSimilarity(termFreqVecA, termFreqVecB); }
Теперь нам нужно импортировать его в нашу модель, чтобы мы могли рассчитать частоту появления. Сначала мы установим оценку как ноль по умолчанию, а затем вычислим ее с помощью функции computeScore.
..... import cosineSim from 'demo-app/utils/cosine-sim'; let faq = DS.Model.extend({ question: DS.attr('string'), answer: DS.attr('string'), score: DS.attr('number', {defaultValue: 0}), computeScore: function(term){ let _this = this; return new Promise(function(resolve, reject){ let sc = cosineSim(term, _this.get('question')); _this.set('score', sc); resolve('score found'); }); }, }); .....
computeScore вычисляет оценку и устанавливает значение score, которое является результатом подобия косинуса .