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 \t
separados, así que preste atención al leer. El estilo de datos es el siguiente
stance
Hay tres campos, a saber FAVOR
,, AGAINST
, NONE
esto 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 stance
campo 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, FAVOR
convertirse __label__A
, AGAINST
convertirse __label__B
, NONE
convertirse__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
, que significa qué porcentaje de los datos originales se muestrean aleatoriamente, si
, 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 autotuneValidationFile
en 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
- Practico sólo se utiliza
text
ystance
dos columnas,target
creo que podemos no podrán ser utilizados - Cuidadosos conjuntos de datos de observación encontraron, de hecho, y la desigual distribución de muestras,
stance
la columnaFAVOR
yAGAINST
los dos valores particularmente grande,NONE
extremadamente rara, que implica el desequilibrio de problema muestras de entrenamiento, puede la muestra, más equilibrado sus proporciones configurado Volver a entrenar - 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.
- Ir directamente a BERT