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 |}} |