Quale tipo di algoritmo "filtro antispam" assegnerà i caratteri per le corrispondenze non esatte?

1

Stavo osservando un esempio di base del filtro antispam usando un algoritmo di regressione logistica e una risposta pubblicata su questa domanda di overflow dello stack: link

Correggimi se ho torto, ma questi algoritmi non sembrano utilizzare alcun tipo di tokenizzazione. Ad esempio, se la mia parola spam è hey , la parola heyyyyy potrebbe passare come falso negativo attraverso il filtro.

C'è un algoritmo o un processo che può essere aggiunto alla regressione logistica di base per migliorare questo? O devo guardare pesantemente a LDA e Topic Modeling? O sarà funzionante la tokenizzazione n-gram di caratteri?

Aggiornamento

Anche se lo sospettavo già, ho eseguito il mio test per essere sicuro. LogisticRegressionWithSGD non utilizza alcun tipo di tokenizzazione (né l'esempio). L'esempio nel link non riesce con moneyyyyy sebbene money attiverà una previsione di spam.

    
posta crockpotveggies 22.02.2016 - 20:54
fonte

1 risposta

0

Quindi, dopo aver esaminato a fondo questo problema per alcune ore, sono stato in grado di suddividerlo in alcune soluzioni diverse e sviluppare una soluzione intermedia per me stesso che, a mio parere, mi porterà a risolvere il mio caso d'uso.

Reti neurali

Sebbene non siano disponibili molte informazioni facilmente accessibili, le reti neurali che utilizzano una tonnellata di dati di addestramento (e caratteristiche appropriate) sono le migliori per lo sviluppo di tali filtri che possono anche continuare ad apprendere su nuove tendenze che riflettono il classificatore. Un ottimo esempio è il filtro antispam di Gmail, che è anche in grado di apprendere le preferenze personali dell'utente.

Modelli di Markov nascosti

Gli HMM hanno la capacità di guardare oltre errori di ortografia intenzionali nel linguaggio (e possono essere più facilmente localizzati) e possono essere classificati anche quando un campione sta intenzionalmente tentando di ingannare il classificatore. Sfortunatamente, non ci sono troppi esempi HMM prontamente disponibili per dimostrare il concetto, anche se questo articolo riguarda Dinamicamente Gli HMM ponderati sono piuttosto descrittivi del concetto.

Tokenizzazione carattere N-grammo

N-gram implicano "affettare" le parole in parti più piccole, che è particolarmente utile per l'elaborazione del linguaggio naturale. La tokenizzazione dei caratteri aggiunge il vantaggio di guardare oltre la maggior parte degli errori ortografici e gergali della lingua per ricavare la parola "originale" (in senso semplice). La tokenizzazione può avvenire durante l'allenamento o durante la classificazione. Per rispondere direttamente alla domanda, questa può essere aggiunta al set di dati o al campione nella pipeline di classificazione della regressione logistica.

e ...

Soluzione intermedia

Basandomi sui limiti del tempo e degli esempi disponibili, sono stato in grado di sbrogliare rapidamente alcune tokenizzazione di base e di fornire un esempio aggiornato basato sulla mia domanda originale. Ho trovato il seguente codice:

import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.mllib.classification.LogisticRegressionWithSGD
import org.apache.spark.mllib.feature.HashingTF
import org.apache.spark.mllib.regression.LabeledPoint


val conf = new SparkConf().setAppName("TokenizationTest").setMaster("local")
val sc = new SparkContext(conf)
// Load 2 types of emails from text files: spam and ham (non-spam).
// Each line has text from one email.
val spam = sc.textFile("testdata/spam.txt")
val ham = sc.textFile("testdata/ham.txt")
println("Loaded sample data")
// Create a HashingTF instance to map email text to vectors of 100 features.
val tf = new HashingTF(numFeatures = 5)
// Each email is split into words, and each word is mapped to one feature.
val spamFeatures = spam.map(email => tf.transform(email.split(" ").map(_.sliding(3,1))))
val hamFeatures = ham.map(email => tf.transform(email.split(" ").map(_.sliding(3,1))))
// Create LabeledPoint datasets for positive (spam) and negative (ham) examples.
val positiveExamples = spamFeatures.map(features => LabeledPoint(1, features))
val negativeExamples = hamFeatures.map(features => LabeledPoint(0, features))
val trainingData = positiveExamples ++ negativeExamples
trainingData.cache() // Cache data since Logistic Regression is an iterative algorithm.
// Create a Logistic Regression learner which uses the LBFGS optimizer.
val lrLearner = new LogisticRegressionWithSGD()
// Run the actual learning algorithm on the training data.
val model = lrLearner.run(trainingData)
// Test on a positive example (spam) and a negative one (ham).
// First apply the same HashingTF feature transformation used on the training data.
val posTestExample = tf.transform("get moneyyyyy ...".split(" "))
val negTestExample = tf.transform("Hi Dad, I started studying Spark the other ...".split(" "))
// Now use the learned model to predict spam/ham for new emails.
println(s"Prediction for positive test example: ${model.predict(posTestExample)}")
println(s"Prediction for negative test example: ${model.predict(negTestExample)}")
sc.stop()

La differenza principale è che ho aggiunto la tokenizzazione ai dati di allenamento:

val spamFeatures = spam.map(email => tf.transform(email.split(" ").map(_.sliding(3,1))))
    val hamFeatures = ham.map(email => tf.transform(email.split(" ").map(_.sliding(3,1))))

In Scala, sliding(n,n) efficacemente tokenizza una stringa. Questo può essere ulteriormente migliorato iterando su diverse dimensioni di token, anche se immagino che si debba prestare attenzione alla creazione di brevi e amp; parole "stop" inutili come at . Ci sono probabilmente molti inconvenienti a questo metodo - tuttavia, immagino di essere sulla strada giusta.

Sebbene le reti neurali siano piuttosto irraggiungibili con il mio set di dati, gli HMM probabilmente saranno la soluzione migliore.

    
risposta data 23.02.2016 - 04:40
fonte

Leggi altre domande sui tag