60 puntos de referencia en la detección del punto de vista de Weibo

AI Institute organizó recientemente un concurso de detección de posición de Weibo , que en realidad es un concurso de clasificación de texto de PNL

línea de base Fasttext

Mi método de línea de base utiliza la segmentación de palabras pkuseg + FastText, el mejor puntaje es 60, la siguiente es una captura de pantalla del puntaje que presenté varias veces

Cargar datos y preprocesar

La biblioteca que se utilizará después de importar

import pkuseg
import random
import pandas as pd
import fasttext
df = pd.read_csv('train.csv', delimiter='\t')

Los datos oficiales, aunque es un archivo csv, pero los campos están \tseparados, así que preste atención al leer. El estilo de datos es el siguiente


stanceHay tres campos, a saber FAVOR,, AGAINST, NONEesto es lo que necesita para predecir el valor final. Sin embargo, a través del análisis cuidadoso de los datos, se puede encontrar que el stancecampo tiene otros valores además de los tres valores anteriores, por lo que primero elimine los otros datos.

drop_list = []
for i in range(len(df)):
    if df.stance[i] != 'FAVOR' and df.stance[i] != 'AGAINST' and df.stance[i] != 'NONE':
        drop_list.append(i)
df.drop(drop_list, inplace=True)

Los datos leídos por FastText deben cumplir __lable__xx text, por ejemplo

__label__A 我 喜欢 打 篮球
__label__B 我 喜欢 鲲鲲
__label__A 我 喜欢 踢 足球

En otras palabras, cada línea representa una muestra, y la etiqueta es la primera, el texto es el siguiente y las dos están separadas por un espacio. La etiqueta debe __label__comenzar con. Por lo tanto, primero debemos convertir la etiqueta de los datos originales, es decir, FAVORconvertirse __label__A, AGAINSTconvertirse __label__B, NONEconvertirse__label__C

mapping = {'FAVOR':'__label__A', 'AGAINST':'__label__B', 'NONE':'__label__C'}
df['stance'] = df['stance'].map(mapping)

Una vez hecho esto, es mejor mezclar los datos

df = df.sample(frac=1)

sample(frac=p)Donde pag [ 0 0 , 1 ] p \ en [0,1] , que significa qué porcentaje de los datos originales se muestrean aleatoriamente, si pag = 1 p = 1 , significa que todos los datos originales se muestrean aleatoriamente, y debido a que es una muestra aleatoria, el orden de los datos originales se altera

Dividir tren y datos de validación

Aquí divido el conjunto de datos en Datos de tren y Datos válidos en una proporción de 7: 3

train_len = int(len(df) * 0.7)
df_train = df.loc[:train_len]
df_val = df.loc[train_len:]

Segmentación de palabras

Desde el estilo de los datos de lectura de FastText, podemos ver que necesitamos segmentar una oración. Aquí uso pkuseg, porque cuando vi su introducción oficial a la API, mencionó que tiene un corpus web

Antes de la segmentación de palabras, encontré algunas palabras comunes en chino e inglés en Internet.

stopwords = []
for line in open('stopwords.txt', encoding='utf-8'):
    stopwords.append(line)

stopwords.append('\n')
stopwords = set(stopwords)

No proporcionaré palabras clave, hay muchas en línea, puede descargarlo usted mismo

Luego lea los datos línea por línea y segmente las palabras, y luego filtre las palabras. Después de hacer todo esto, de acuerdo con el formato requerido por FastText, concatene las cadenas y guárdelas en el archivo

def dump_file(df, filename, mode='train'):
    seg = pkuseg.pkuseg(model_name='web')
    with open(filename, 'w',encoding='utf-8') as f:
        for i in df.index.values:
            segs = seg.cut(df.text[i])
            segs = filter(lambda x:x not in stopwords, segs)  #去掉停用词
#             segs = filter(lambda x:len(x)>1,segs)
            segs = filter(lambda x:x.startswith('http')==False, segs)
            segs = filter(lambda x:x.startswith('.')==False, segs)
            segs = filter(lambda x:x.startswith('-')==False, segs)
            segs = filter(lambda x:x.startswith(',')==False, segs)
            segs = filter(lambda x:x.startswith('。')==False, segs)
            segs = filter(lambda x:x.startswith('…')==False, segs)
            segs = filter(lambda x:x.startswith('/')==False, segs)
            segs = filter(lambda x:x.startswith('—')==False, segs)
            segs = filter(lambda x:x.startswith('、')==False, segs)
            segs = filter(lambda x:x.startswith(':')==False, segs)
            segs = filter(lambda x:x.startswith('~')==False, segs)
            segs = filter(lambda x:x.startswith('[')==False, segs)
            segs = filter(lambda x:x.startswith(']')==False, segs)
            segs = filter(lambda x:(x.isalpha() and len(x) == 7) == False, segs)
            string = ''
            for j in segs:
                string = string + ' ' + j
            if mode == 'test':
                string = string.lstrip()
            else:
                string = df.stance[i] + ' ' + string
                string = string.lstrip()
            f.write(string + '\n')
dump_file(df_train, 'train.txt', 'train')
dump_file(df_val, 'val.txt', 'train')

Fasttext

Primero, clone la versión clonada de su repositorio oficial de github (use pip install fasttext directamente es la versión estable)

$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ pip install .

Debido a que hay un parámetro autotuneValidationFileen la última versión de desarrollo que puede buscar automáticamente el parámetro que maximiza acc durante el entrenamiento. fastText también es muy simple de usar

clf = fasttext.train_supervised(input='train.txt', autotuneValidationFile='val.txt')

Es suficiente especificar el conjunto de entrenamiento y la ruta del conjunto de prueba para ayudar a encontrar los parámetros óptimos. Úselo si desea guardar el modelo

clf.save_model('fasttext_model')

Predecir y enviar

Básicamente, si lo haces de acuerdo con mi método, la puntuación máxima en el conjunto de verificación hasta ahora es de aproximadamente 60

Luego es para predecir el conjunto de pruebas. Una vez completada la predicción, es suficiente enviar.

test = pd.read_csv('test.csv', delimiter='\t')
dump_file(test, 'test.txt', 'test')

labels = []
for line in open('test.txt', encoding='utf-8'):
    if line != '':
        line = line.strip('\n')
        labels.append(clf.predict(line)[0][0])
        
test['idx'] = range(len(test))
test['stance'] = labels
mapping = {'__label__A':'FAVOR','__label__B':'AGAINST','__label__C':'NONE'}
test['stance'] = test['stance'].map(mapping)
test = test.drop(['target', 'text'], axis=1)

test.to_csv('test_pred.csv',index=False,header=False)

Mejorar

  1. Practico sólo se utiliza texty stancedos columnas, targetcreo que podemos no podrán ser utilizados
  2. Cuidadosos conjuntos de datos de observación encontraron, de hecho, y la desigual distribución de muestras, stancela columna FAVORy AGAINSTlos dos valores particularmente grande, NONEextremadamente rara, que implica el desequilibrio de problema muestras de entrenamiento, puede la muestra, más equilibrado sus proporciones configurado Volver a entrenar
  3. La configuración de la palabra del filtro es un poco más detallada. Si observa más de cerca el conjunto de datos después de la segmentación de palabras, debería poder encontrar que en realidad hay muchas palabras de spam, como URL, códigos de verificación de 7 dígitos, emoticones, etc.
  4. Ir directamente a BERT
175 artículos originales publicados · 226 elogiados · 190,000 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_37236745/article/details/104892859
Recomendado
Clasificación