classifier.js
Version:
:robot: Natural language processing with Javascript
81 lines (68 loc) • 2.49 kB
text/typescript
import { TokensList } from './tokensList'
const { isArray } = Array
import { getAbsoluteValue, sumFunc, toNormalizedString } from './lib'
import { TokenProps } from './tokensList'
export class Category {
name: string
relatedCategories = new Set<string>()
sentences: string[] = []
inferedTokens: TokensList
private isUpdated = true
constructor(name: string, tokens: [string, TokenProps][] = []) {
this.name = name
this.inferedTokens = new TokensList(name)
for (const [name, value] of tokens)
this.inferedTokens.tokens.set(name, value)
}
addSentence(sentence: string, relatedCategories: string[]) {
this.isUpdated = false
const normalizedSentence = this.normalizeData(sentence)
this.sentences?.push(normalizedSentence)
relatedCategories.forEach(category => this.relatedCategories.add(category))
return this
}
private normalizeData(sentence: string) {
return toNormalizedString(sentence.toLowerCase())
}
getWords(input: string[] | string) {
return isArray(input) ? input.join(' ').split(' ') : input.split(' ')
}
private isARelatedCategory(category: string) {
return this.relatedCategories.has(category)
}
analize(categories: Category[]) {
if(this.isUpdated) return this
this.getWords(this.sentences).forEach((word) => {
this.inferedTokens.increaseRelevancy(word)
})
categories
.filter((category) => category.name !== this.name && !this.isARelatedCategory(category.name))
.forEach((category) =>
category
.getWords(category.sentences)
.forEach((word) => this.inferedTokens.decreaseRelevancy(word))
)
this.isUpdated = true
return this
}
private resolveScore(score: number[]) {
const positiveValues = score.filter((item) => item >= 0)
const negativeValues = score.filter((item) => item < 0)
const sumOfPositiveValues = positiveValues.reduce(sumFunc, 0)
const resolvedNegativeScore = getAbsoluteValue(
negativeValues.reduce(sumFunc, 0)
)
return sumOfPositiveValues / (resolvedNegativeScore + sumOfPositiveValues)
}
classify(sentence: string, categories: Category[]) {
this.analize(categories)
const classifiedWords = this.getWords(this.normalizeData(sentence)).map(
(word) => this.inferedTokens.test(word)
)
const score = this.resolveScore(classifiedWords)
return score > 0 ? score : 0
}
getTokens() {
return [...this.inferedTokens.tokens.entries()]
}
}