Je pense que beaucoup dans les discussions tendues sur Internet ont été accusés d'être des robots, des trolls et payés par le Kremlin, Kiev ou Washington. Mais comment vraiment identifier ceux-là ou simplement ceux qui essaient de transmettre activement leur opinion aux autres?
Prenons, par exemple, quatre textes (commentaires):
text_1 = ' , '
text_2 = ' , , '
text_3 = ' '
text_4 = ' , , , '
D'un point de vue humain, il y a certainement une similitude dans les premier et deuxième commentaires, ils sont écrits sur une personne et caractérisent ses aspects positifs. Et ils n'ont rien à voir avec les textes trois et quatre.
Comment arrivez-vous mathématiquement au même résultat?
Il est ridicule de comparer le nombre de mots identiques dans les deux textes. Mais le problème se pose immédiatement - comment comparer les mots intelligent et intelligent ? La lemmatisation du texte n'est pas toujours appropriée, car les bibliothèques prêtes à l'emploi ne supportent pas beaucoup de langues.
Dans de tels moments, il est justifié d'utiliser l' algorithme Shingle qui divise le texte en n parties, dont la taille est choisie empiriquement pour une tâche spécifique.
Exemple:
Texte 1 pour n = 3
['', '', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', '', '', '', '', ' ', ' ', ' ', '', '', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', '', '', '', '', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', '', '', '', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', '', '', '', '', '', '']
Texte 1 pour n = 5
['', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', '', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', ' ', ' ', ' ', ' ', ' ', '', '', '', '']
Calculons la similitude des premier et deuxième / premier et quatrième textes pour n (1.9) par la formule:
sim = len(set(Shingles_1) & set(Shingles_2)) / len(set(Shingles_1) | set(Shingles_2)))
ShingleSize: 1
0.9166666666666666 / 0.7857142857142857
ShingleSize: 2
0.5196078431372549 / 0.40350877192982454
ShingleSize: 3
0.3404255319148936 / 0.2375
ShingleSize: 4
0.28205128205128205 / 0.18497109826589594
ShingleSize: 5
0.2289156626506024 / 0.13812154696132597
ShingleSize: 6
0.1896551724137931 / 0.10752688172043011
ShingleSize: 7
0.15730337078651685 / 0.07894736842105263
ShingleSize: 8
0.13333333333333333 / 0.057291666666666664
ShingleSize: 9
0.10989010989010989 / 0.04145077720207254
Une image naturelle, avec une augmentation de la longueur, le nombre total de bardeaux augmente et le rapport du total des bardeaux au volume total diminue. Donc, pour les gros volumes de textes, il est préférable d'utiliser la longueur des bardeaux de 5 à 8, et lorsque vous travaillez avec des bardeaux courts, par exemple des tweets ou des commentaires - 2-4.
Mais revenons à la pratique, prenons les données pré-collectées du populaire portail de divertissement russe. Lien vers kaggle .
Pour recueillir les discussions les plus animées, la balise (section) - Politique a été choisie, total collecté:
- 944 messages tagués politique
- 267000 commentaires à eux
- dont plus de 100 caractères ~ 140 000
Passons au code:
effacement du texte et division en bardeaux:
def clean_text(text):
text = text.split('\n')
text = list(filter(None, text))
text = ' '.join(text)
text = re.sub(r"http\S+", "", text)
text = re.sub(r'[^\w\s]', '', text)
shingle = [text[i:i + ShingleSize] for i in range(len(text))][:-ShingleSize]
return ','.join(shingle)
Si nous ne prenons que les commentaires de plus de 100 caractères, alors le nombre d'itérations de comparaison est: , ce qui est assez important et le traitement même en mode multi-thread prendra un temps assez long.
Par conséquent, nous ne comparerons pas par paires, mais avec des matrices m * n , en utilisant la similitude cosinus
où m est le nombre de lignes, qui est éventuellement sélectionné en fonction de la quantité de RAM, et n est le nombre de colonnes, le nombre total de tous les bardeaux;
Implémentation de l'algorithme:
csrMatrix = []
idArray = []
textArray = []
for i in range(ChunkSize, sparse_matrix.shape[0] + ChunkSize, ChunkSize):
temp = sparse_matrix[i - ChunkSize:i - 1]
idArray.append(corpusId[i - ChunkSize:i - 1])
textArray.append(OriginalCorpus[i - ChunkSize:i - 1])
csrMatrix.append(temp)
matrixCombinations = itertools.combinations_with_replacement(range(len(csrMatrix)), 2)
Avec m = 20 000 et la longueur des bardeaux = 8, nous obtenons 7 matrices de 20 000 * ≈8800 000 en taille et donc 21 itérations de comparaison. Beaucoup mieux déjà.
def Sim(A, B, C, D):
similarities = cosine_similarity(B[A[0]].astype(np.float32), B[A[1]].astype(np.float32))
x, y = np.where(similarities > similarityPercent)
res = []
for k, j in zip(x, y):
if D[A[0]][k] != D[A[1]][j]:
res.append((D[A[0]][k], C[A[0]][k], similarities[k][j].item(), D[A[1]][j], C[A[1]][j]))
return res
s = pool.starmap(Sim, zip(matrixCombinations, itertools.repeat(csrMatrix), itertools.repeat(textArray), itertools.repeat(idArray)))
s = [item for sublist in s for item in sublist]
Pour réduire l'espace occupé, nous utilisons également le type de données float32. Sa précision est tout à fait suffisante pour que l'algorithme fonctionne correctement.
Les résultats du travail sont saisis dans la base de données MySQL pour un traitement ultérieur. Donc, par exemple, regroupons les commentaires, en comptant pour chacun la similitude avec ses paires:
SELECT FirstText, SUM(sim) as c FROM pikabu.similarity GROUP BY FirstId ORDER BY c DESC
Meilleurs matchs:
- Le commentaire a été supprimé. Raison: ce compte a été supprimé.
- Le commentaire a été supprimé. Raison: insulter les utilisateurs.
- Le commentaire a été supprimé. Raison: insultes, communication grossière et provocations.
- Le commentaire a été supprimé. Raison: Il est interdit de publier des commentaires dont le seul but est de provoquer l'hostilité ou l'incitation à l'hostilité, et les commentaires avec des appels à la violence ou au harcèlement sont interdits.
La situation standard pour la discussion politique sur Internet.
En supprimant les liens, les messages de l'administration, et autres bruits, nous passons directement à l'analyse de la charge sémantique des commentaires:
Huit matchs
DaimosShip,2020-08-14 23:03:48,
,
DaimosShip,2020-08-14 23:05:41,
,
DaimosShip,2020-08-14 23:05:52,
,
DaimosShip,2020-08-14 23:05:26,
,
DaimosShip,2020-08-14 23:05:22,
,
DaimosShip,2020-08-14 23:07:02,
,
DaimosShip,2020-08-14 23:06:53,
,
DaimosShip,2020-08-14 23:06:18,
,
,
DaimosShip,2020-08-14 23:05:41,
,
DaimosShip,2020-08-14 23:05:52,
,
DaimosShip,2020-08-14 23:05:26,
,
DaimosShip,2020-08-14 23:05:22,
,
DaimosShip,2020-08-14 23:07:02,
,
DaimosShip,2020-08-14 23:06:53,
,
DaimosShip,2020-08-14 23:06:18,
,
Un homme a écrit 8 messages identiques sur le même sujet en cinq minutes, concernant les événements en Biélorussie. Au total, 260 messages de cet auteur sont entrés dans la base de données, un rapide coup d'œil sur eux montre clairement une attitude négative évidente à l'égard de la situation en Biélorussie, l'utilisateur lui-même est en avance sur la courbe et appelle ses adversaires des robots comme arguments.
Et son frère était un observateur aux élections:
DaimosShip, 2020-08-18 22:52:41
Mon frère était un observateur - ils n'étaient autorisés nulle part
6 autres matchs
NoisePanzer,2017-11-20 14:58:26,
17 . , , , 80% ( !) .
NoisePanzer,2017-11-20 15:33:26,
. . ( !) . , , . ( ) , .
NoisePanzer,2017-11-20 15:26:55,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:51:46,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:52:14,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:53:22,
. ( !) . , , . ( ) , .
17 . , , , 80% ( !) .
NoisePanzer,2017-11-20 15:33:26,
. . ( !) . , , . ( ) , .
NoisePanzer,2017-11-20 15:26:55,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:51:46,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:52:14,
. . . ( !) . , , . ( ) , .
NoisePanzer,2017-11-21 03:53:22,
. ( !) . , , . ( ) , .
L'auteur est clairement fan de la littérature historique allemande
Et 4 de plus
Kumuj,2018-03-25 01:46:10,
, . ?
Kumuj,2018-03-25 01:53:56,
, . ?
Kumuj,2018-03-25 01:46:26,
, . ?
Kumuj,2018-03-25 01:42:29,
, . ?
, . ?
Kumuj,2018-03-25 01:53:56,
, . ?
Kumuj,2018-03-25 01:46:26,
, . ?
Kumuj,2018-03-25 01:42:29,
, . ?
L'homme cherche des traces de l'usine de trolls. Salut collègue.
Allez-y: 6 personnes citent le même livre dans des sujets différents - Attention, échec et mat !!!
Strannik196,2018-03-21 23:53:00,
:"« , «-22» : , , . , — . , : , , . .— , — . — . . , . , . . :— …»"
Fynjif18,2020-09-09 13:44:56,
.— , — . — , «-22» : , , . , — . , : , , .
wakeonlan,2020-06-23 01:38:29,
«-22» : , , ** . ** , — . , : * , , .
KKirill1992,2017-06-18 00:06:30,
, "«-22»" . , , , . . - ? , ?
nezabuddha,2018-11-01 15:29:56,
ru.m.wikipedia.org/wiki/-22 . , .
ihateyou,2016-09-19 02:52:14,
, «-22» : , , . , — . , : , , . .— , — . — . . , . , . . :— … "«Empire V»"
:"« , «-22» : , , . , — . , : , , . .— , — . — . . , . , . . :— …»"
Fynjif18,2020-09-09 13:44:56,
.— , — . — , «-22» : , , . , — . , : , , .
wakeonlan,2020-06-23 01:38:29,
«-22» : , , ** . ** , — . , : * , , .
KKirill1992,2017-06-18 00:06:30,
, "«-22»" . , , , . . - ? , ?
nezabuddha,2018-11-01 15:29:56,
ru.m.wikipedia.org/wiki/-22 . , .
ihateyou,2016-09-19 02:52:14,
, «-22» : , , . , — . , : , , . .— , — . — . . , . , . . :— … "«Empire V»"
L'auteur tente de transmettre au reste des données sur la croissance du niveau de soutien à l'URSS
EtovamneTo,2020-08-18 01:50:22,
, , … . . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-08-18 00:50:15,
, , , , . , IQ . : . : . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-08-27 23:22:35,
. *****(). 18 . . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-09-10 03:32:13,
? ? 25. 2010 44 . 2020 274 . ? . , 18-24 https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-09-09 19:00:42,
. , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
, , … . . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-08-18 00:50:15,
, , , , . , IQ . : . : . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-08-27 23:22:35,
. *****(). 18 . . , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-09-10 03:32:13,
? ? 25. 2010 44 . 2020 274 . ? . , 18-24 https://www.levada.ru/2019/06/24/chernovik/
EtovamneTo,2020-09-09 19:00:42,
. , 18-24 , , 2008- 2019- , . , , « », . . , , – , ( 18-24- ). , , , , – « » ( 14 ..) «, , » ( 18 ..).https://www.levada.ru/2019/06/24/chernovik/
Les exemples donnés étaient en surface. Pour identifier des relations plus étroites, il est nécessaire d'élargir l'ensemble de données d'un ordre de grandeur, non seulement par la quantité d'informations, mais également par des intervalles de temps. Cela permettra d'identifier plus précisément les thèmes clés autour desquels se construisent les discussions, leurs initiateurs, d'analyser les horodatages des événements et leur corrélation.
Mais même sur un tel ensemble, avec une analyse manuelle détaillée, par exemple, en considérant des connexions uniques, vous pouvez trouver quelque chose d'intéressant, qui donne lieu à une réflexion et à un travail ultérieur.
GitHub
PS Traitement de la matrice 140 000 * 8800000 a pris environ 7 minutes sur le processeur rayzen 5 1600
À l'avenir, je prévois de continuer ce sujet, je serai heureux de critiques et de suggestions.