¿Cómo puedo crear un modelo para distinguir los tweets sobre Apple (Inc.) de los tweets sobre manzana (fruta)?

85

Vea a continuación 50 tweets sobre "manzana". He etiquetado a mano las coincidencias positivas sobre Apple Inc. Están marcadas como 1 a continuación.

Aquí hay un par de líneas:

1|“@chrisgilmer: Apple targets big business with new iOS 7 features http://bit.ly/15F9JeF ”. Finally.. A corp iTunes account!
0|“@Zach_Paull: When did green skittles change from lime to green apple? #notafan” @Skittles
1|@dtfcdvEric: @MaroneyFan11 apple inc is searching for people to help and tryout all their upcoming tablet within our own net page No.
0|@STFUTimothy have you tried apple pie shine?
1|#SuryaRay #India Microsoft to bring Xbox and PC games to Apple, Android phones: Report: Microsoft Corp... http://dlvr.it/3YvbQx  @SuryaRay

Aquí está el conjunto de datos total: http://pastebin.com/eJuEb4eB

Necesito construir un modelo que clasifique a "Apple" (Inc). del resto.

No estoy buscando una descripción general del aprendizaje automático, sino un modelo real en el código (se prefiere Python ).

SAL
fuente
18
Básicamente quieres esto: en.wikipedia.org/wiki/Bayesian_spam_filtering
eddi
1
Usted etiqueta manualmente sus datos, pero quiere bibliotecas que escalen. ¿Es esto supervisado o no supervisado?
dan
1
Eddi, gracias por el comentario. Ver el correo electrónico filtrado de correo realmente ayudó a que algo hiciera clic en mi cerebro. Pude ver un ejemplo de la vida real de lo que estaba tratando de hacer, simplemente aplicado de manera diferente.
SAL
5
Reconocimiento de entidad nombrada: nlp.stanford.edu/software/CRF-NER.shtml .
Neil McGuigan
1
Fascinante @NeilMcGuigan. Pegué parte del texto en su demostración ( nlp.stanford.edu:8080/ner/process ) y me impresionó cómo los diferentes modelos clasificaban las palabras.
Ryan

Respuestas:

39

Lo haría de la siguiente manera:

  1. Divida la oración en palabras, normalícelas, construya un diccionario
  2. Con cada palabra, almacene cuántas veces aparecieron en tweets sobre la empresa y cuántas veces aparecieron en tweets sobre la fruta; estos tweets deben ser confirmados por un humano.
  3. Cuando ingrese un nuevo tweet, busque cada palabra del tweet en el diccionario, calcule una puntuación ponderada: las palabras que se usan con frecuencia en relación con la empresa obtendrían una puntuación alta de la empresa y viceversa; las palabras que se usan con poca frecuencia, o que se usan tanto con la empresa como con la fruta, no tendrían mucho valor.
AMADANON Inc.
fuente
2
Gracias por tu respuesta a esto. Su respuesta junto con un comentario anterior realmente me ayudó a encontrar una solución. ¿Puedes ayudarme a perfeccionar esta solución?
SAL
10
Ésta es una descripción informal de la clasificación bayesiana.
sanityinc
1
Prefiero "implementación de pseudocódigo de la clasificación bayesiana" :)
AMADANON Inc.
73

Lo que busca se llama Reconocimiento de entidad nombrada . Es una técnica estadística que (más comúnmente) usa campos aleatorios condicionales para encontrar entidades con nombre, basándose en haber sido entrenado para aprender cosas sobre entidades con nombre.

Básicamente, analiza el contenido y el contexto de la palabra (mirando hacia atrás y hacia adelante algunas palabras) para estimar la probabilidad de que la palabra sea una entidad con nombre.

Un buen software puede observar otras características de las palabras, como su longitud o forma (como "Vcv" si comienza con "Vocal-consonante-vocal")

Una muy buena biblioteca (GPL) es la NER de Stanford

Aquí está la demostración: http://nlp.stanford.edu:8080/ner/

Algunos ejemplos de texto para probar:

Estaba comiendo una manzana en la sede de Apple y pensé en Apple Martin, la hija del tipo de Coldplay.

(los clasificadores de 3 clases y 4 clases lo hacen bien)

Neil McGuigan
fuente
5
Eso fue realmente interesante. ¿Es posible ver el código de english.conll.4class.distsim.crf.ser.gz? Me encantaría ver cómo se construye algo como esto.
Ryan
El código de NER es de código abierto, pero los datos que utilizaron en las conferencias CONLL no lo son. Sin embargo, puede encontrar Reuters Corpus en línea en NIST.
Neil McGuigan
31

Tengo un sistema semi-funcional que resuelve este problema, de código abierto usando scikit-learn, con una serie de publicaciones de blog que describen lo que estoy haciendo. El problema que estoy abordando es la desambiguación del sentido de las palabras (elegir una de las múltiples opciones de sentido de las palabras ), que no es lo mismo que el reconocimiento de entidades nombradas. Mi enfoque básico es algo competitivo con las soluciones existentes y (fundamentalmente) es personalizable.

Existen algunas herramientas comerciales de NER (OpenCalais, DBPedia Spotlight y AlchemyAPI) que pueden brindarle un resultado comercial suficientemente bueno. ¡Pruébelo primero!

Usé algunos de estos para un proyecto de cliente (consulto usando NLP / ML en Londres), pero no estaba contento con su recuperación ( precisión y recuperación ). Básicamente, pueden ser precisos (cuando dicen "Esto es Apple Inc" suelen ser correctos), pero con poca memoria (rara vez dicen "Esto es Apple Inc", aunque para un humano el tweet es obviamente sobre Apple Inc). Pensé que sería un ejercicio intelectualmente interesante crear una versión de código abierto adaptada a los tweets. Aquí está el código actual: https://github.com/ianozsvald/social_media_brand_disambiguator

Notaré: no estoy tratando de resolver el problema generalizado de desambiguación del sentido de las palabras con este enfoque, solo desambiguación de marca (empresas, personas, etc.) cuando ya tiene su nombre. Por eso creo que este enfoque sencillo funcionará.

Comencé esto hace seis semanas y está escrito en Python 2.7 usando scikit-learn. Utiliza un enfoque muy básico. Vectorizo ​​usando un vectorizador de conteo binario (solo cuento si aparece una palabra, no cuántas veces) con 1-3  n-gramos . No escalo con TF-IDF (TF-IDF es bueno cuando tiene un documento de longitud variable; para mí, los tweets son solo una o dos oraciones, y los resultados de mis pruebas no mostraron mejoras con TF-IDF).

Utilizo el tokenizador básico que es muy básico pero sorprendentemente útil. Ignora @ # (por lo que pierde algo de contexto) y, por supuesto, no expande una URL. Luego entreno usando regresión logística , y parece que este problema es algo linealmente separable (muchos términos para una clase no existen para la otra). Actualmente estoy evitando cualquier extracción / limpieza (estoy probando la cosa más simple posible que podría funcionar).

El código tiene un README completo, y debería poder ingerir sus tweets con relativa facilidad y luego seguir mis sugerencias para la prueba.

Esto funciona para Apple, ya que la gente no come ni bebe computadoras Apple, ni escribimos ni jugamos con frutas, por lo que las palabras se dividen fácilmente en una categoría u otra. Es posible que esta condición no se mantenga al considerar algo como #definanciamiento para el programa de televisión (donde la gente también usa #definanciamiento en relación con la Primavera Árabe, partidos de cricket, revisión de exámenes y una banda de música). Es posible que aquí se requieran enfoques más inteligentes.

Tengo una serie de publicaciones en el blog que describen este proyecto, incluida una presentación de una hora que di en el grupo de usuarios de BrightonPython (que se convirtió en una presentación más corta para 140 personas en DataScienceLondon).

Si usa algo como LogisticRegression (donde obtiene una probabilidad para cada clasificación), puede elegir solo las clasificaciones confiables, y de esa manera puede forzar una alta precisión al negociar contra el recuerdo (para obtener resultados correctos, pero menos). Tendrá que ajustar esto a su sistema.

Aquí hay un posible enfoque algorítmico usando scikit-learn:

  • Use un vectorizador de conteo binario (no creo que los conteos de términos en mensajes cortos agreguen mucha información ya que la mayoría de las palabras ocurren solo una vez)
  • Comience con un clasificador de árbol de decisión. Tendrá un rendimiento explicable (consulte Sobreajuste con un árbol de decisiones para ver un ejemplo).
  • Pasar a la regresión logística
  • Investigue los errores generados por los clasificadores (lea la salida exportada de DecisionTree o mire los coeficientes en LogisticRegression, revise los tweets mal clasificados a través del Vectorizador para ver cómo se ve la representación subyacente de Bag of Words; habrá menos tokens allí que comenzaste en el tweet sin procesar, ¿hay suficiente para una clasificación?)
  • Mire mi código de ejemplo en https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py para obtener una versión funcional de este enfoque

Cosas para considerar:

  • Necesita un conjunto de datos más grande. Estoy usando 2000 tweets etiquetados (me tomó cinco horas) y, como mínimo, desea un conjunto equilibrado con> 100 por clase (consulte la nota de sobreajuste a continuación)
  • Mejore el tokenizador (muy fácil con scikit-learn) para mantener # @ en tokens, y tal vez agregue un detector de marca en mayúsculas (como notas del usuario @ user2425429)
  • Considere un clasificador no lineal (como la sugerencia de @ oiez anterior) cuando las cosas se pongan más difíciles. Personalmente, encontré que LinearSVC funciona peor que la regresión logística (pero eso puede deberse al espacio de características de alta dimensión que aún tengo que reducir).
  • Un etiquetador de voz específico para tweets (en mi humilde opinión, no el de Standford como sugiere @Neil; en mi experiencia, funciona mal en la gramática de Twitter deficiente)
  • Una vez que tenga muchos tokens, probablemente querrá hacer una reducción de dimensionalidad (aún no lo he intentado; consulte la publicación de mi blog sobre penalización LogisticRegression l1 l2)

Re. sobreajuste. En mi conjunto de datos con 2000 elementos, tengo una instantánea de 10 minutos de Twitter de los tweets de 'apple'. Aproximadamente 2/3 de los tweets son para Apple Inc, 1/3 para otros usos de Apple. Saco un subconjunto equilibrado (aproximadamente 584 filas, creo) de cada clase y hago una validación cruzada de cinco veces para el entrenamiento.

Dado que solo tengo una ventana de tiempo de 10 minutos, tengo muchos tweets sobre el mismo tema, y ​​esta es probablemente la razón por la que mi clasificador funciona tan bien en relación con las herramientas existentes: se habrá sobreajustado a las funciones de entrenamiento sin generalizar bien (mientras que el comercial existente las herramientas funcionan peor en esta tienda de instantáneas, pero de manera más confiable en un conjunto más amplio de datos). Ampliaré mi ventana de tiempo para probar esto como un trabajo posterior.

Ian Ozsvald
fuente
No he tenido el placer de revisar tu código y tratar de duplicar / emular / educar, pero te debo una disculpa por no otorgar los 50 puntos completos de la recompensa. Estuve fuera de SO durante el fin de semana y no cumplí la fecha límite para otorgarlo. Afortunadamente, la comunidad de SO intervino y consideró oportuno otorgarle 25 puntos.
Ryan
1
No hay problema :-) El código, el archivo README y las publicaciones del blog deberían darte una idea de mi enfoque. Es deliberadamente simple pero parece funcionar bien.
Ian Ozsvald
12

Puede hacer lo siguiente:

  1. Haga un dictado de palabras que contengan su recuento de ocurrencia en tweets relacionados con frutas y empresas. Esto se puede lograr alimentándolo con algunos tweets de muestra cuya inclinación conocemos.

  2. Utilizando suficientes datos anteriores, podemos averiguar la probabilidad de que aparezca una palabra en un tweet sobre apple inc.

  3. Multiplica las probabilidades individuales de las palabras para obtener la probabilidad del tweet completo.

Un ejemplo simplificado:

p_f = Probabilidad de tweets de frutas.

p_w_f = Probabilidad de que aparezca una palabra en un tweet de frutas.

p_t_f = Probabilidad combinada de que todas las palabras del tweet ocurran un tweet de frutas = p_w1_f * p_w2_f * ...

p_f_t = Probabilidad de fruta dado un tweet en particular.

p_c, p_w_c, p_t_c, p_c_t son valores respectivos para la empresa.

Se agrega un suavizador laplaciano de valor 1 para eliminar el problema de frecuencia cero de palabras nuevas que no están en nuestra base de datos.

old_tweets = {'apple pie sweet potatoe cake baby https://vine.co/v/hzBaWVA3IE3': '0', ...}
known_words = {}
total_company_tweets = total_fruit_tweets =total_company_words = total_fruit_words = 0

for tweet in old_tweets:
    company = old_tweets[tweet]
    for word in tweet.lower().split(" "):
        if not word in known_words:
            known_words[word] = {"company":0, "fruit":0 }
        if company == "1":
            known_words[word]["company"] += 1
            total_company_words += 1
        else:
            known_words[word]["fruit"] += 1
            total_fruit_words += 1

    if company == "1":
        total_company_tweets += 1
    else:
        total_fruit_tweets += 1
total_tweets = len(old_tweets)

def predict_tweet(new_tweet,K=1):
    p_f = (total_fruit_tweets+K)/(total_tweets+K*2)
    p_c = (total_company_tweets+K)/(total_tweets+K*2)
    new_words = new_tweet.lower().split(" ")

    p_t_f = p_t_c = 1
    for word in new_words:
        try:
            wordFound = known_words[word]
        except KeyError:
            wordFound = {'fruit':0,'company':0}
        p_w_f = (wordFound['fruit']+K)/(total_fruit_words+K*(len(known_words)))
        p_w_c = (wordFound['company']+K)/(total_company_words+K*(len(known_words)))
    p_t_f *= p_w_f
    p_t_c *= p_w_c

    #Applying bayes rule
    p_f_t = p_f * p_t_f/(p_t_f*p_f + p_t_c*p_c)
    p_c_t = p_c * p_t_c/(p_t_f*p_f + p_t_c*p_c)
    if p_c_t > p_f_t:
        return "Company"
    return "Fruit"
Sudipta
fuente
9

Si no tiene problemas para usar una biblioteca externa, le recomiendo scikit-learn, ya que probablemente pueda hacer esto mejor y más rápido que cualquier cosa que pueda codificar usted mismo. Solo haría algo como esto:

Construye tu corpus. Hice las comprensiones de la lista para mayor claridad, pero dependiendo de cómo se almacenan sus datos, es posible que deba hacer cosas diferentes:

def corpus_builder(apple_inc_tweets, apple_fruit_tweets):
    corpus = [tweet for tweet in apple_inc_tweets] + [tweet for tweet in apple_fruit_tweets]
    labels = [1 for x in xrange(len(apple_inc_tweets))] + [0 for x in xrange(len(apple_fruit_tweets))]
    return (corpus, labels)

Lo importante es que terminas con dos listas que se ven así:

([['apple inc tweet i love ios and iphones'], ['apple iphones are great'], ['apple fruit tweet i love pie'], ['apple pie is great']], [1, 1, 0, 0])

[1, 1, 0, 0] representan las etiquetas positivas y negativas.

Luego, ¡crea un Pipeline! Pipeline es una clase de scikit-learn que facilita encadenar los pasos de procesamiento de texto para que solo tenga que llamar a un objeto al entrenar / predecir:

def train(corpus, labels)
    pipe = Pipeline([('vect', CountVectorizer(ngram_range=(1, 3), stop_words='english')),
                        ('tfidf', TfidfTransformer(norm='l2')),
                        ('clf', LinearSVC()),])
    pipe.fit_transform(corpus, labels)
    return pipe

Dentro del Pipeline hay tres pasos de procesamiento. CountVectorizer tokeniza las palabras, las divide, las cuenta y transforma los datos en una matriz dispersa. El TfidfTransformer es opcional, y es posible que desee eliminarlo dependiendo de la calificación de precisión (hacer pruebas de validación cruzada y una búsqueda en cuadrícula de los mejores parámetros es un poco complicado, por lo que no entraré en él aquí). LinearSVC es un algoritmo de clasificación de texto estándar.

Finalmente, predice la categoría de tweets:

def predict(pipe, tweet):
    prediction = pipe.predict([tweet])
    return prediction

Nuevamente, el tweet debe estar en una lista, así que asumí que ingresaba a la función como una cadena.

Ponlos todos en una clase o lo que sea, y listo. Al menos, con este ejemplo muy básico.

No probé este código, por lo que es posible que no funcione si solo copia y pega, pero si desea usar scikit-learn, debería darle una idea de por dónde empezar.

EDITAR: intenté explicar los pasos con más detalle.

oiez
fuente
6

El uso de un árbol de decisiones parece funcionar bastante bien para este problema. Al menos produce una mayor precisión que un clasificador bayes ingenuo con mis características elegidas.

Si desea jugar con algunas posibilidades, puede usar el siguiente código, que requiere que nltk esté instalado. El libro nltk también está disponible gratuitamente en línea, por lo que es posible que desee leer un poco sobre cómo funciona todo esto: http://nltk.googlecode.com/svn/trunk/doc/book/ch06.html

#coding: utf-8
import nltk
import random
import re

def get_split_sets():
    structured_dataset = get_dataset()
    train_set = set(random.sample(structured_dataset, int(len(structured_dataset) * 0.7)))
    test_set = [x for x in structured_dataset if x not in train_set]

    train_set = [(tweet_features(x[1]), x[0]) for x in train_set]
    test_set = [(tweet_features(x[1]), x[0]) for x in test_set]
    return (train_set, test_set)

def check_accurracy(times=5):
    s = 0
    for _ in xrange(times):
        train_set, test_set = get_split_sets()
        c = nltk.classify.DecisionTreeClassifier.train(train_set)
        # Uncomment to use a naive bayes classifier instead
        #c = nltk.classify.NaiveBayesClassifier.train(train_set)
        s += nltk.classify.accuracy(c, test_set)

    return s / times


def remove_urls(tweet):
    tweet = re.sub(r'http:\/\/[^ ]+', "", tweet)
    tweet = re.sub(r'pic.twitter.com/[^ ]+', "", tweet)
    return tweet

def tweet_features(tweet):
    words = [x for x in nltk.tokenize.wordpunct_tokenize(remove_urls(tweet.lower())) if x.isalpha()]
    features = dict()
    for bigram in nltk.bigrams(words):
        features["hasBigram(%s)" % ",".join(bigram)] = True
    for trigram in nltk.trigrams(words):
        features["hasTrigram(%s)" % ",".join(trigram)] = True  
    return features

def get_dataset():
    dataset = """copy dataset in here
"""
    structured_dataset = [('fruit' if x[0] == '0' else 'company', x[2:]) for x in dataset.splitlines()]
    return structured_dataset

if __name__ == '__main__':
    print check_accurracy()
Paul dobla
fuente
1
¿como funciona esto? No veo sus "funciones elegidas" en su código. ¿Elige funciones automáticamente según el conjunto de entrenamiento? ¿O está almacenado en dict()otro lugar? Creo que si el conjunto de entrenamiento de uno es lo suficientemente grande, ¿no debería una computadora ser capaz de descubrir las características por sí misma? (¿sin supervisión?)
Ryan
2
Las características se extraen mediante la función tweet_features. Básicamente, elimina las URL de los tweets y luego crea un diccionario de características cuyas entradas se leen algo como 'hasBigram (foo, bar)' = True.
Paul Dubs
1
Entonces, ¿ 'hasBigram(foo,bar)' = Truedónde se incluye la cadena de tweets foo bar? Entonces, ¿crea bigrams y trigramas para cada tweet y lo marca en la característica positiva dict()? Por lo tanto, dado el tweet, "alpha beta gamma delta"construirá dict () bigrams alpha,beta; beta,gamma; and gamma,delta;y trigrams para alpha,beta,gammay beta,gamma,delta? ¿Y a partir de los bi y tri gramas positivos y negativos dados, los clasificadores de árbol de decisión o bayes pueden hacer su magia?
Ryan
2
Exactamente. Al usar el clasificador de bayes, también puede obtener las características más útiles llamando a "show_most_informative_features ()" en él.
Paul Dubs
Paul, construí una versión php cruda de esto y estás absolutamente en lo cierto. Esta es una forma muy eficaz de crear un diccionario ponderado. Creo que esto podría escalar fácilmente sin tener que crear manualmente todas las palabras clave. Espero aprender más sobre cómo hacer esto dentro de una biblioteca de aprendizaje automático estándar.
Ryan
5

Gracias por los comentarios hasta ahora. Aquí hay una solución funcional que preparé con PHP. Todavía estaría interesado en escuchar de otros un enfoque más algorítmico para esta misma solución.

<?php

// Confusion Matrix Init
$tp = 0;
$fp = 0;
$fn = 0;
$tn = 0;
$arrFP = array();
$arrFN = array();

// Load All Tweets to string
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://pastebin.com/raw.php?i=m6pP8ctM');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$strCorpus = curl_exec($ch);
curl_close($ch);

// Load Tweets as Array
$arrCorpus = explode("\n", $strCorpus);
foreach ($arrCorpus as $k => $v) {
    // init
    $blnActualClass = substr($v,0,1);
    $strTweet = trim(substr($v,2));

    // Score Tweet
    $intScore = score($strTweet);

    // Build Confusion Matrix and Log False Positives & Negatives for Review
    if ($intScore > 0) {
        if ($blnActualClass == 1) {
            // True Positive
            $tp++;
        } else {
            // False Positive
            $fp++;
            $arrFP[] = $strTweet;
        }
    } else {
        if ($blnActualClass == 1) {
            // False Negative
            $fn++;
            $arrFN[] = $strTweet;
        } else {
            // True Negative
            $tn++;
        }
    }
}

// Confusion Matrix and Logging
echo "
           Predicted
            1     0
Actual 1   $tp     $fp
Actual 0    $fn    $tn

";

if (count($arrFP) > 0) {
    echo "\n\nFalse Positives\n";
    foreach ($arrFP as $strTweet) {
        echo "$strTweet\n";
    }
}

if (count($arrFN) > 0) {
    echo "\n\nFalse Negatives\n";
    foreach ($arrFN as $strTweet) {
        echo "$strTweet\n";
    }
}

function LoadDictionaryArray() {
    $strDictionary = <<<EOD
10|iTunes
10|ios 7
10|ios7
10|iPhone
10|apple inc
10|apple corp
10|apple.com
10|MacBook
10|desk top
10|desktop
1|config
1|facebook
1|snapchat
1|intel
1|investor
1|news
1|labs
1|gadget
1|apple store
1|microsoft
1|android
1|bonds
1|Corp.tax
1|macs
-1|pie
-1|clientes
-1|green apple
-1|banana
-10|apple pie
EOD;

    $arrDictionary = explode("\n", $strDictionary);
    foreach ($arrDictionary as $k => $v) {
        $arr = explode('|', $v);
        $arrDictionary[$k] = array('value' => $arr[0], 'term' => strtolower(trim($arr[1])));
    }
    return $arrDictionary;
}

function score($str) {
    $str = strtolower($str);
    $intScore = 0;
    foreach (LoadDictionaryArray() as $arrDictionaryItem) {
        if (strpos($str,$arrDictionaryItem['term']) !== false) {
            $intScore += $arrDictionaryItem['value'];
        }
    }
    return $intScore;
}
?>

Los resultados anteriores:

           Predicted
            1     0
Actual 1   31     1
Actual 0    1    17


False Positives
1|Royals apple #ASGame @mlb @ News Corp Building http://instagram.com/p/bBzzgMrrIV/


False Negatives
-1|RT @MaxFreixenet: Apple no tiene clientes. Tiene FANS// error.... PAGAS por productos y apps, ergo: ERES CLIENTE.
SAL
fuente
4

En todos los ejemplos que proporcionó, se hizo referencia a Apple (inc) como A pple o apple inc , por lo que una posible forma podría ser buscar:

  • una "A" mayúscula en Apple

  • un "inc" después de apple

  • palabras / frases como "SO", "sistema operativo", "Mac", "iPhone", ...

  • o una combinación de ellos

usuario2425429
fuente
1
En la función hice un strtolower para filtrar las letras mayúsculas. Un poco tosco, pero funcionó.
SAL
@SAL No esperaba que fuera muy útil, pero si tienes un límite de tiempo, entonces ...
user2425429
4

Para simplificar un poco las respuestas basadas en campos aleatorios condicionales ... el contexto es enorme aquí. Querrá destacar en esos tweets que muestran claramente a Apple la empresa frente a Apple la fruta. Permítanme esbozar una lista de características aquí que podrían ser útiles para comenzar. Para obtener más información, busque fragmentación de frases nominales y algo llamado etiquetas BIO. Ver ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Palabras circundantes: cree un vector de características para la palabra anterior y la siguiente, o si desea más características, tal vez las 2 palabras anteriores y las 2 siguientes. No desea demasiadas palabras en el modelo o no coincidirá muy bien con los datos. En Procesamiento del lenguaje natural, querrá mantener esto lo más general posible.

Otras características que se pueden obtener de las palabras circundantes son las siguientes:

Si el primer carácter es mayúscula

Si el último carácter de la palabra es un punto.

La parte gramatical de la palabra (busque el etiquetado de parte gramatical)

El texto mismo de la palabra

No recomiendo esto, pero para dar más ejemplos de funciones específicamente para Apple:

WordIs (Apple)

NextWordIs (Inc.)

Tú entiendes. Piense en el reconocimiento de entidades nombradas como una descripción de una secuencia y luego use algunas matemáticas para decirle a una computadora cómo calcular eso.

Tenga en cuenta que el procesamiento del lenguaje natural es un sistema basado en canalizaciones. Por lo general, divide las cosas en oraciones, pasa a la tokenización y luego realiza parte del etiquetado de voz o incluso el análisis de dependencia.

Todo esto es para obtener una lista de características que puede usar en su modelo para identificar lo que está buscando.

Adam Gibson
fuente
3

Hay una biblioteca realmente buena para procesar texto en lenguaje natural en Python llamada nltk. Deberías echarle un vistazo.

Una estrategia que podría probar es mirar n-gramas (grupos de palabras) con la palabra "manzana" en ellos. Es más probable que algunas palabras se usen junto a "manzana" cuando se habla de la fruta, otras cuando se habla de la empresa, y puede usarlas para clasificar los tweets.

Scott Ritchie
fuente
1
Gracias Manetheran. No soy el póster original, pero también me interesa la respuesta. Por la recompensa, estoy buscando un código (incluso usando nltk) que pueda ayudarme a comenzar en la dirección correcta con una tarea de aprendizaje automático de "hola mundo". La manzana (inc) contra la manzana (fruta) parece una asignación perfecta.
Ryan
3

Utilice LibShortText . Esta utilidad de Python ya se ha ajustado para que funcione en tareas de categorización de texto corto y funciona bien. Lo máximo que tendrá que hacer es escribir un bucle para elegir la mejor combinación de banderas. Lo usé para hacer una clasificación supervisada de actos de habla en correos electrónicos y los resultados fueron hasta un 95-97% precisos (¡durante 5 veces la validación cruzada!).

Y proviene de los creadores de LIBSVM y LIBLINEAR, cuya implementación de máquina de vectores de soporte (SVM) se usa en sklearn y cran, por lo que puede estar razonablemente seguro de que su implementación no tiene errores.

Pushpendre
fuente
2

Haga un filtro de inteligencia artificial para distinguir Apple Inc (la empresa) de la manzana (la fruta). Dado que estos son tweets, defina su conjunto de entrenamiento con un vector de 140 campos, cada campo es el carácter escrito en el tweet en la posición X (0 a 139). Si el tweet es más corto, simplemente dé un valor para estar en blanco.

Luego, construya un conjunto de entrenamiento lo suficientemente grande para obtener una buena precisión (subjetiva a su gusto). Asigne un valor de resultado a cada tweet, un tweet de Apple Inc obtiene 1 (verdadero) y un tweet de manzana (fruta) obtiene 0. Sería un caso de aprendizaje supervisado en una regresión logística .

Eso es aprendizaje automático, generalmente es más fácil de codificar y funciona mejor. Tiene que aprender del conjunto que le da, y no está codificado.

No conozco Python , por lo que no puedo escribir el código para él, pero si se tomara más tiempo para la lógica y la teoría del aprendizaje automático, es posible que desee ver la clase que estoy siguiendo.

Prueba el curso de Coursera Machine Learning de Andrew Ng . Aprenderá el aprendizaje automático en MATLAB u Octave , pero una vez que obtenga los conceptos básicos, podrá escribir el aprendizaje automático en cualquier idioma si comprende las matemáticas simples (simple en regresión logística).

Es decir, obtener el código de alguien no le permitirá comprender lo que está sucediendo en el código de aprendizaje automático. Es posible que desee invertir un par de horas en el tema para ver qué está pasando realmente.

Fawar
fuente
Gracias Fawar. Esperaba algo de código en este "hola mundo" para este propósito exacto: aprender cómo funciona ML. Sin embargo, buscaré la clase. Se ve bien.
Ryan
0

Recomendaría evitar respuestas que sugieran reconocimiento de entidad. Porque esta tarea es una clasificación de texto primero y un reconocimiento de entidad en segundo lugar (puede hacerlo sin el reconocimiento de entidad).

Creo que el camino más rápido hacia los resultados será Spacy + Prodigy . Spacy tiene un modelo bien pensado para el idioma inglés, por lo que no tienes que construir el tuyo propio. Mientras que prodigy permite crear rápidamente conjuntos de datos de entrenamiento y ajustar el modelo de espacio para sus necesidades.

Si tiene suficientes muestras, puede tener un modelo decente en 1 día.

Oscuro
fuente
Al mismo tiempo, spaCytiene nercomponente de tubería, ¿no sería beneficioso para esta clasificación? Supongo que su modelo puede reconocer Apple(ya que es una de las empresas más grandes y conocidas del mundo) mucho mejor que un modelo que se le ocurra en un día.
Szymon Maszke
@Szymon: NER puede ayudar o no. Según tengo entendido, desea utilizar entidades con nombre (el hecho de que están presentes en el texto) como una característica para la tarea de clasificación principal. Aparentemente, NER no tendrá una precisión del 100% ya que existe un alto nivel de ambigüedad. Entonces, el modelo de clasificación principal decidirá bajo qué circunstancias confiará en esta característica. Puede resultar (creo que es muy probable) que un modelo de clasificación básico dé un peso muy bajo a los resultados del modelo NER. Y esto significa que pasará tiempo en NER, que (casi) no se usa.
Dim
No es lo que quise decir. Simplemente cree a spacy.Docpartir de cada texto, repita sus NER con doc.entsy verifique si algún NER tiene un .textatributo igual a Apple. Dato curioso, su primer ejemplo consiste en Apple.
Szymon Maszke
Y si alguien quisiera hacer un modelo, probablemente involucraría RNN / CNN y similares, sintonizarlos en consecuencia, encontrar arquitectura, tipos de celda, etc., no creo que modelos más fáciles manejen bien la desambiguación y el contexto. ¿Por qué facilitarle la vida (a menos que desee aprender algo en el camino), si alguien ya lo ha hecho por usted?
Szymon Maszke
@SzymonMaszke tu modelo es más complicado y más difícil de entrenar. Para que su modelo funcione para el propósito mencionado, no solo tiene que encontrar un NE, sino también encontrarlo en el lugar correcto (token). Con el modelo de categorización, le sugiero que optimice el modelo para su objetivo principal: identificar si es la empresa Apple o la fruta Apple. Eso es más fácil de entrenar y, por lo tanto, lo más probable es que sea más preciso.
Dim