Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
ia:desinformadores [2025/01/29 01:30] anonimo |
ia:desinformadores [2025/02/01 03:57] (actual) anonimo |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| + | 1º Tomar como base los principales desinformadores de España, que son los que proporcionan una información más heterogenea en datos\\ | ||
| + | 2º Extraer los títulos de los vídeos,shorts y directos de youtube mediante web scrapping\\ | ||
| + | 3º Limpiarlos de caracteres extraños, tildes, artículos y preposiciones que no sirven para el propósito mediante el editor de textos sed\\ | ||
| + | 4º Hacer pruebas midiendo el grado de similitud ideológica de diferentes usuarios/seguidores respecto a dichos desinformadores\\ | ||
| + | |||
| + | |||
| **Extraemos los títulos de los vídeos, shorts y directos mediante web scrapping** | **Extraemos los títulos de los vídeos, shorts y directos mediante web scrapping** | ||
| <code python> | <code python> | ||
| Línea 174: | Línea 180: | ||
| python3 raspado.py > geoestratego.txt | python3 raspado.py > geoestratego.txt | ||
| </code> | </code> | ||
| + | El resultado está en éste archivo {{ :ia:desinformadores.gz |}}\\ | ||
| + | |||
| **El .txt hay que prepararlo y no lo está, ésto contienen las 4 primeras líneas** | **El .txt hay que prepararlo y no lo está, ésto contienen las 4 primeras líneas** | ||
| <code bash> | <code bash> | ||
| Línea 185: | Línea 193: | ||
| <code bash> | <code bash> | ||
| cat geoestratego.txt | grep Título | sed '/^Título: ,/d;s/^Título: //g;s/, Enlace: .*$//g;s/[A-Z]/\L&/g;y/áéíóú/aeiou/;s/[^a-zñ0-9 ]/ /g;s/ \+/ /g' | perl -ple 's/[^a-zñÑ0-9 ]//gi' | perl -ple '$_=lc' | sed 's/ \+/ /g;s/^ //g' > geoestratego_.txt | cat geoestratego.txt | grep Título | sed '/^Título: ,/d;s/^Título: //g;s/, Enlace: .*$//g;s/[A-Z]/\L&/g;y/áéíóú/aeiou/;s/[^a-zñ0-9 ]/ /g;s/ \+/ /g' | perl -ple 's/[^a-zñÑ0-9 ]//gi' | perl -ple '$_=lc' | sed 's/ \+/ /g;s/^ //g' > geoestratego_.txt | ||
| + | </code> | ||
| + | **volvemos a limpiar**\\ | ||
| + | <code bash> | ||
| + | sed -Ei 's/ de / /g;s/ la / /g;s/ los / /g;s/ las / /g;s/ y / /g;s/ el / /g;s/ del / /g;s/ al / /g;s/ a / /g;s/^el |^la |^los |^las //g;s/^lo //g;s/ en / /g;s/ un / /g;s/^ //g;' geoestratego_.txt | ||
| </code> | </code> | ||
| **El .txt ya está preparado, éstas son las 4 primeras líneas** | **El .txt ya está preparado, éstas son las 4 primeras líneas** | ||
| <code bash> | <code bash> | ||
| cat geoestratego_.txt | sed -n '1,4p' | cat geoestratego_.txt | sed -n '1,4p' | ||
| - | el plan final de biden para desestabilizar el mundo | + | plan final biden para desestabilizar mundo |
| marcha militar coronel pedro baños | marcha militar coronel pedro baños | ||
| - | pedro baños y la geopolitica 2 3 | + | pedro baños geopolitica 2 3 |
| - | los medios de comunicacion pierden el control | + | medios comunicacion pierden control |
| cat geoestratego_.txt | wc -l | cat geoestratego_.txt | wc -l | ||
| Línea 201: | Línea 214: | ||
| **Preparación de los datos**\\ | **Preparación de los datos**\\ | ||
| <code python> | <code python> | ||
| - | import os | + | """ |
| - | from transformers import AutoTokenizer | + | MIT License |
| - | + | ||
| - | # Ruta a la carpeta con los archivos | + | Copyright (c) 2025 wiki.acosadores.net |
| - | ruta_listados = "./listados" | + | |
| + | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| + | of this software and associated documentation files (the "Software"), to deal | ||
| + | in the Software without restriction, including without limitation the rights | ||
| + | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| + | copies of the Software, and to permit persons to whom the Software is | ||
| + | furnished to do so, subject to the following conditions: | ||
| + | |||
| + | The above copyright notice and this permission notice shall be included in all | ||
| + | copies or substantial portions of the Software. | ||
| + | |||
| + | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| + | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| + | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| + | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| + | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| + | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| + | SOFTWARE. | ||
| + | """ | ||
| + | from sklearn.feature_extraction.text import TfidfVectorizer | ||
| + | from sklearn.metrics.pairwise import cosine_similarity | ||
| - | # Códigos asociados a cada listado | + | # 1. Leer los archivos .txt |
| - | codigos_asociados = { | + | with open("usuario.txt", "r", encoding="utf-8") as f1, open("geoestratego_.txt", "r", encoding="utf-8") as f2: |
| - | "geoestratego_.txt": [1, 2], | + | frases1 = f1.readlines() # Frases de usuario.txt |
| - | "listado2.txt": [1], | + | frases2 = f2.readlines() # Frases de geoestratego.txt |
| - | } | + | |
| - | # Tokenizer de BERT para procesar palabras | + | # 2. Vectorizar las frases de ambos ficheros con TF-IDF |
| - | tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") | + | vectorizer = TfidfVectorizer() |
| - | + | tfidf_matrix1 = vectorizer.fit_transform(frases1) # Matriz TF-IDF para fichero1 | |
| - | # Leer los listados y tokenizarlos | + | tfidf_matrix2 = vectorizer.transform(frases2) # Transformamos fichero2 con el mismo modelo |
| - | listados = {} | + | |
| - | for archivo in os.listdir(ruta_listados): | + | |
| - | if archivo.endswith(".txt"): | + | |
| - | with open(os.path.join(ruta_listados, archivo), "r", encoding="utf-8") as f: | + | |
| - | frases = f.read().splitlines() # Cada línea es una frase | + | |
| - | tokenized = [tokenizer(f, truncation=True, padding='max_length', max_length=20, return_tensors="pt") for f in frases] | + | |
| - | listados[archivo] = { | + | |
| - | "frases": tokenized, | + | |
| - | "codigos": codigos_asociados.get(archivo, []) | + | |
| - | } | + | |
| - | </code> | + | |
| - | + | ||
| - | **Definición del modelo con LSTM**\\ | + | |
| - | <code python> | + | |
| - | import torch | + | |
| - | import torch.nn as nn | + | |
| - | + | ||
| - | class LSTMFrases(nn.Module): | + | |
| - | def __init__(self, embed_dim, hidden_dim, output_dim): | + | |
| - | super(LSTMFrases, self).__init__() | + | |
| - | self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True) | + | |
| - | self.fc = nn.Linear(hidden_dim * 2, output_dim) # Bidireccional, por eso 2x hidden_dim | + | |
| - | self.sigmoid = nn.Sigmoid() | + | |
| - | + | ||
| - | def forward(self, x): | + | |
| - | _, (hidden, _) = self.lstm(x) # hidden: (2, batch_size, hidden_dim) | + | |
| - | hidden = torch.cat((hidden[0], hidden[1]), dim=1) # Concatenar direcciones | + | |
| - | output = self.fc(hidden) | + | |
| - | return self.sigmoid(output) | + | |
| - | </code> | + | |
| - | + | ||
| - | **Entrenamiento** | + | |
| - | <code python> | + | |
| - | from torch.utils.data import DataLoader, Dataset | + | |
| - | + | ||
| - | # Dataset para manejar frases y etiquetas | + | |
| - | class FrasesDataset(Dataset): | + | |
| - | def __init__(self, frases, codigos, embed_dim): | + | |
| - | self.frases = frases | + | |
| - | self.codigos = codigos | + | |
| - | self.embed_dim = embed_dim | + | |
| - | + | ||
| - | def __len__(self): | + | |
| - | return len(self.frases) | + | |
| - | + | ||
| - | def __getitem__(self, idx): | + | |
| - | tokens = self.frases[idx]["input_ids"].squeeze(0) | + | |
| - | mask = self.frases[idx]["attention_mask"].squeeze(0) | + | |
| - | etiqueta = torch.tensor(self.codigos, dtype=torch.float) | + | |
| - | return tokens, mask, etiqueta | + | |
| - | + | ||
| - | # Configuración del modelo y entrenamiento | + | |
| - | embed_dim = 768 # Dimensión de BERT | + | |
| - | hidden_dim = 128 | + | |
| - | epochs = 5 | + | |
| - | batch_size = 4 | + | |
| - | learning_rate = 0.001 | + | |
| - | + | ||
| - | modelos = {} | + | |
| - | for nombre, datos in listados.items(): | + | |
| - | num_codigos = len(datos["codigos"]) | + | |
| - | modelo = LSTMFrases(embed_dim, hidden_dim, num_codigos) | + | |
| - | dataset = FrasesDataset(datos["frases"], datos["codigos"], embed_dim) | + | |
| - | dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) | + | |
| - | + | ||
| - | optimizer = torch.optim.Adam(modelo.parameters(), lr=learning_rate) | + | |
| - | criterio = nn.BCELoss() | + | |
| - | + | ||
| - | # Entrenamiento | + | |
| - | modelo.train() | + | |
| - | for epoch in range(epochs): | + | |
| - | for tokens, mask, etiquetas in dataloader: | + | |
| - | optimizer.zero_grad() | + | |
| - | salida = modelo(tokens.float()) # Los tokens deben estar en formato flotante | + | |
| - | loss = criterio(salida, etiquetas) | + | |
| - | loss.backward() | + | |
| - | optimizer.step() | + | |
| - | print(f"Listado {nombre}, Epoch {epoch+1}, Loss: {loss.item()}") | + | |
| - | + | ||
| - | modelos[nombre] = modelo | + | |
| - | </code> | + | |
| - | + | ||
| - | **Calcular similitud entre una frase nueva y los listados usando el modelo LSTM**\\ | + | |
| - | <code python> | + | |
| - | from torch.nn.functional import cosine_similarity | + | |
| - | def calcular_similitud(frase, listado, modelo): | + | # 3. Calcular la similitud coseno entre frases de fichero1 y fichero2 |
| - | modelo.eval() | + | cosine_sim = cosine_similarity(tfidf_matrix1, tfidf_matrix2) |
| - | tokens = tokenizer(frase, truncation=True, padding='max_length', max_length=20, return_tensors="pt") | + | |
| - | input_ids = tokens["input_ids"] | + | |
| - | mask = tokens["attention_mask"] | + | |
| - | with torch.no_grad(): | + | |
| - | vector_frase = modelo(input_ids.float()) | + | |
| - | total_similitud = 0 | + | |
| - | for tokens_listado in listado["frases"]: | + | |
| - | input_ids_listado = tokens_listado["input_ids"] | + | |
| - | with torch.no_grad(): | + | |
| - | vector_listado = modelo(input_ids_listado.float()) | + | |
| - | similitud = cosine_similarity(vector_frase, vector_listado).item() | + | |
| - | total_similitud += similitud | + | |
| - | return total_similitud / len(listado["frases"]) | + | |
| - | # Ejemplo de evaluación | + | # 4. Mostrar los resultados |
| - | nuevo_listado = ["la vida es hermosa", "estoy lleno de energía"] | + | print("Similitudes Coseno entre las frases de usuario.txt y geoestratego_.txt:") |
| - | for frase in nuevo_listado: | + | for i in range(len(frases1)): |
| - | for nombre, modelo in modelos.items(): | + | for j in range(len(frases2)): |
| - | similitud = calcular_similitud(frase, listados[nombre], modelo) | + | print(f"Similitud entre frase {i + 1} de usuario y frase {j + 1} de geoestratego_: {cosine_sim[i, j]:.2f}") |
| - | print(f"Similitud de '{frase}' con {nombre}: {similitud:.2f}") | + | |
| </code> | </code> | ||
| - | {{ :ia:desinformadores.gz |}} | ||