import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch import os import warnings warnings.filterwarnings('ignore') class TurkishSentimentAnalyzer: def __init__(self): self.device = "cuda" if torch.cuda.is_available() else "cpu" print(f"Using device: {self.device}") # sentiment model model_name = "savasy/bert-base-turkish-sentiment-cased" self.tokenizer = AutoTokenizer.from_pretrained(model_name) self.model = AutoModelForSequenceClassification.from_pretrained(model_name).to(self.device) # Lojistik ve satıcı kelimeleri self.logistics_seller_words = { 'kargo', 'kargocu', 'paket', 'paketleme', 'teslimat', 'teslim', 'gönderi', 'gönderim', 'ulaştı', 'ulaşım', 'geldi', 'kurye', 'satıcı', 'mağaza', 'sipariş', 'trendyol', 'tedarik', 'stok', 'fiyat', 'ücret', 'para', 'bedava', 'indirim', 'kampanya', 'havale', 'ödeme', 'garanti', 'fatura' } def predict_sentiment(self, text): """Tek bir metin için sentiment tahmini yap""" if not isinstance(text, str) or len(text.strip()) == 0: return {"label": "Nötr", "score": 0.5} try: inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512, padding=True).to(self.device) with torch.no_grad(): outputs = self.model(**inputs) probs = torch.nn.functional.softmax(outputs.logits, dim=1) prediction = probs.cpu().numpy()[0] # İki sınıflı model için (positive/negative) score = float(prediction[1]) # Pozitif sınıfın olasılığı # Daha hassas skor eşikleri if score > 0.75: # Yüksek güvenle pozitif label = "Pozitif" elif score < 0.25: # Yüksek güvenle negatif label = "Negatif" elif score > 0.55: # Hafif pozitif eğilim label = "Pozitif" elif score < 0.45: # Hafif negatif eğilim label = "Negatif" else: label = "Nötr" return {"label": label, "score": score} except Exception as e: print(f"Error in sentiment prediction: {e}") return {"label": "Nötr", "score": 0.5} def filter_product_reviews(self, df): """Ürün ile ilgili olmayan yorumları filtrele""" def is_product_review(text): if not isinstance(text, str): return False return not any(word in text.lower() for word in self.logistics_seller_words) filtered_df = df[df['Yorum'].apply(is_product_review)].copy() print(f"\nFiltreleme İstatistikleri:") print(f"Toplam yorum sayısı: {len(df)}") print(f"Ürün yorumu sayısı: {len(filtered_df)}") print(f"Filtrelenen yorum sayısı: {len(df) - len(filtered_df)}") print(f"Filtreleme oranı: {((len(df) - len(filtered_df)) / len(df) * 100):.2f}%") return filtered_df def analyze_reviews(self, df): """Tüm yorumları analiz et""" print("\nSentiment analizi başlatılıyor...") filtered_df = self.filter_product_reviews(df) # Sentiment analizi results = [] for text in filtered_df['Yorum']: sentiment = self.predict_sentiment(text) results.append(sentiment) filtered_df['sentiment_score'] = [r['score'] for r in results] filtered_df['sentiment_label'] = [r['label'] for r in results] return filtered_df def create_visualizations(self, df): """Analiz sonuçlarını görselleştir""" if not os.path.exists('images'): os.makedirs('images') # 1. Sentiment Dağılımı plt.figure(figsize=(12, 6)) sns.countplot(data=df, x='sentiment_label', order=['Pozitif', 'Nötr', 'Negatif']) plt.title('Sentiment Dağılımı') plt.tight_layout() plt.savefig('images/sentiment_distribution.png', bbox_inches='tight', dpi=300) plt.close() # 2. Yıldız-Sentiment İlişkisi plt.figure(figsize=(12, 6)) df_mean = df.groupby('Yıldız Sayısı')['sentiment_score'].mean().reset_index() sns.barplot(data=df_mean, x='Yıldız Sayısı', y='sentiment_score') plt.title('Yıldız Sayısına Göre Ortalama Sentiment Skoru') plt.tight_layout() plt.savefig('images/star_sentiment_relation.png', bbox_inches='tight', dpi=300) plt.close() # 3. Sentiment Score Dağılımı plt.figure(figsize=(12, 6)) sns.histplot(data=df, x='sentiment_score', bins=30) plt.title('Sentiment Score Dağılımı') plt.tight_layout() plt.savefig('images/sentiment_score_distribution.png', bbox_inches='tight', dpi=300) plt.close() def print_statistics(self, df): """Analiz istatistiklerini yazdır""" print("\nSentiment Analizi Sonuçları:") print("-" * 50) sentiment_counts = df['sentiment_label'].value_counts() total_reviews = len(df) for label, count in sentiment_counts.items(): percentage = (count / total_reviews) * 100 print(f"{label}: {count} yorum ({percentage:.2f}%)") print("\nYıldız Bazlı Sentiment Skorları:") print("-" * 50) star_means = df.groupby('Yıldız Sayısı')['sentiment_score'].mean() for star, score in star_means.items(): print(f"{star} Yıldız ortalama sentiment skoru: {score:.3f}") def main(): df = pd.read_csv('data/macbook_product_comments_with_ratings.csv') analyzer = TurkishSentimentAnalyzer() print("Analiz başlatılıyor...") analyzed_df = analyzer.analyze_reviews(df) print("\nGörselleştirmeler oluşturuluyor...") analyzer.create_visualizations(analyzed_df) analyzer.print_statistics(analyzed_df) output_file = 'sentiment_analyzed_reviews.csv' analyzed_df.to_csv(output_file, index=False, encoding='utf-8-sig') print(f"\nSonuçlar '{output_file}' dosyasına kaydedildi.") if __name__ == "__main__": main()