Récemment, Sberbank dans l'article Tout ce dont nous avons besoin est la génération a suggéré une approche inhabituelle pour filtrer les textes de mauvaise qualité (spam technique et spam de modèle).
Nous avons complété cette approche avec une autre heuristique: nous avons fait la compression de textes en utilisant zlib et avons écarté les plus fortement et faiblement compressées, puis nous avons appliqué la classification. Plage de compression choisie empiriquement pour le texte normal × 1,2 - × 8 (moins de 1,2 - caractères aléatoires et indésirable technique, plus de 8 - modèle de spam).
L'approche est certainement intéressante et mérite d'être adoptée. Mais le taux de compression zlib sur les textes de qualité n'a-t-il pas une dépendance non linéaire de la longueur du texte compressé? Allons vérifier.
Prenons un corpus textuel de phrases dont la longueur varie de 50 à 280 caractères:
import zlib
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.optimize import curve_fit
with open('/content/test.txt', 'r', encoding='utf-8') as f:
text = f.read()
sntc = text.split('\n')
l_sntc = [] #
k_zlib = [] #
for s in sntc:
l_sntc.append(len(s))
k_zlib.append(len(s) / len(zlib.compress(s.encode(), -1)))
Voyons comment la longueur des phrases de haute qualité affecte le taux de compression.
Pour ça:
1. Prenons la plage de longueurs de phrases avec la fréquence la plus élevée (25 - 75 percentile). Dans notre cas, ce sont des longueurs de 92 à 175 caractères:
mp_1 = np.percentile(np.array(l_sntc), [25, 75])
print(': ' + str(mp_1))
2. . 25 (25 + w) 75 (75 - w) ( ), w - ( 2.5 ).
:
w = 2.5 #
mp_2 = np.percentile(np.array(l_sntc), [25 + w, 75 - w])
dl = int(min(mp_2[0] - mp_1[0], mp_1[1] - mp_2[1]))
print(' : ' + str(dl))
3 .
+- 3 :
#
id_sntc = range(len(sntc)) #
x = zip(l_sntc, id_sntc)
xs = sorted(x, key = lambda tup: tup[0])
l_sntc_s = [x[0] for x in xs]
id_snt_s = [x[1] for x in xs]
gr = 0 #
k_gr = [[]] #
l_gr = [[]] #
sl0 = l_sntc_s[l_sntc_s.index(mp_1[0])] #
nt = l_sntc_s.index(mp_1[1])
for i in range(nt, len(l_sntc_s)):
if l_sntc_s[i] > l_sntc_s[nt]:
nt = i
break
for i in range(l_sntc_s.index(mp_1[0]), nt):
if l_sntc_s[i] > sl0 + dl:
sl0 = l_sntc_s[i]
k_gr.append([])
l_gr.append([])
gr += 1
else:
k_gr[gr].append(k_zlib[id_snt_s[i]])
l_gr[gr].append(l_sntc_s[i])
print(' : ' + str(gr))
20 .
3. , :
x = [0]
y = [0]
for i in range(gr + 1):
x.append(np.percentile(np.array(l_gr[i]), 50))
y.append(np.percentile(np.array(k_gr[i]), 50))
:
x - , y - .
x = np.array(x)
y = np.array(y)
#
def func(x, a, b):
return a * x ** b
popt, pcov = curve_fit(func, x, y, (0.27, 0.24), maxfev=10 ** 6)
a, b = popt
print('a = {0}\nb = {1}'.format(*tuple(popt)))
print(' : ' + str(np.corrcoef(y, a * x ** b)[0][1]))
a = 0.17601951773514363, b = 0.3256903074228561, : 0.9999489378452683
:
( 50 - 280 ) , . "c" "y = " ( ), , :
c = np.percentile(np.array(k_zlib), 50)
graph = plt.figure()
axes = graph.add_axes([0, 0, 1, 1])
axes.set_xlabel(' ')
axes.set_ylabel(' ')
axes.set_title(' ')
axes.plot([60, 280], [c, c], color='r')
axes.plot(range(60, 281), a * np.array(range(60, 281)) ** b, color='b')
. ~130 , ~130 - . . , .
, . , .
k_zlib_f = np.array(k_zlib) * c / (a * np.array(l_sntc) ** b)
, :
dans notre cas, les phrases ont déjà été débarrassées de leurs indésirables techniques, donc à titre d'exemple, nous filtrons uniquement les phrases spammées:
p_zlib_1 = np.percentile(np.array(k_zlib), 99.95)
p_zlib_2 = np.percentile(np.array(k_zlib_f), 99.95)
for i in range(len(sntc)):
if k_zlib_f[i] > p_zlib_2 and k_zlib[i] <= p_zlib_1:
print(sntc[i])
Comme vous pouvez le voir, ce sont des phrases courtes pour lesquelles le taux de compression a été sous-estimé . En pratique, les phrases de même longueur sont assez rares dans le corpus. En règle générale, la gamme de longueurs est assez importante.
Le code complet de l'ordinateur portable est publié sur GitHub .
Ce sera peut-être utile pour quelqu'un. J'ai adopté cette approche pour moi-même comme un moyen relativement simple et efficace de me débarrasser des indésirables techniques et des modèles de spam.