Add Sentiment Analysis lab
This commit is contained in:
33
SentimentAnalysisLab/build.gradle
Normal file
33
SentimentAnalysisLab/build.gradle
Normal file
@@ -0,0 +1,33 @@
|
||||
import org.springframework.boot.gradle.plugin.SpringBootPlugin
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
description = "Sentiment Analysis Lab"
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom SpringBootPlugin.BOM_COORDINATES
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
|
||||
implementation 'com.opencsv:opencsv:5.7.1'
|
||||
implementation 'edu.stanford.nlp:stanford-corenlp:4.5.9:models'
|
||||
implementation 'edu.stanford.nlp:stanford-corenlp:4.5.9'
|
||||
|
||||
runtimeOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.example.senti;
|
||||
|
||||
import edu.stanford.nlp.ling.CoreAnnotations;
|
||||
import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations;
|
||||
import edu.stanford.nlp.pipeline.*;
|
||||
import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
|
||||
import edu.stanford.nlp.util.CoreMap;
|
||||
import com.opencsv.CSVReader;
|
||||
import com.opencsv.exceptions.CsvException;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
|
||||
public class ProductReviewAnalyzer {
|
||||
|
||||
private StanfordCoreNLP pipeline;
|
||||
|
||||
public static void main(String[] args) {
|
||||
ProductReviewAnalyzer analyzer = new ProductReviewAnalyzer();
|
||||
analyzer.initialize();
|
||||
|
||||
try {
|
||||
// Load reviews from CSV
|
||||
List<String[]> reviews = analyzer.loadReviews("/product_reviews.csv");
|
||||
Map<String, Integer> sentimentDistribution = new LinkedHashMap<>();
|
||||
sentimentDistribution.put("Very Positive", 0);
|
||||
sentimentDistribution.put("Positive", 0);
|
||||
sentimentDistribution.put("Neutral", 0);
|
||||
sentimentDistribution.put("Negative", 0);
|
||||
sentimentDistribution.put("Very Negative", 0);
|
||||
|
||||
System.out.println("=== Review Sentiment Analysis ===");
|
||||
for (String[] review : reviews) {
|
||||
if (review[0].equals("review_id")) continue; // Skip header
|
||||
|
||||
String sentiment = analyzer.analyzeSentiment(review[1]);
|
||||
sentimentDistribution.put(sentiment, sentimentDistribution.get(sentiment) + 1);
|
||||
|
||||
System.out.printf("Review %2s: %-60s - %s\n",
|
||||
review[0],
|
||||
shortenText(review[1], 55),
|
||||
sentiment);
|
||||
}
|
||||
|
||||
// Generate report
|
||||
analyzer.generateReport(sentimentDistribution, reviews.size() - 1);
|
||||
|
||||
} catch (IOException | CsvException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
// Set up pipeline properties
|
||||
Properties props = new Properties();
|
||||
props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
|
||||
props.setProperty("coref.algorithm", "neural");
|
||||
this.pipeline = new StanfordCoreNLP(props);
|
||||
}
|
||||
|
||||
public List<String[]> loadReviews(String filePath) throws IOException, CsvException {
|
||||
try (CSVReader reader = new CSVReader(new InputStreamReader(new ClassPathResource(filePath).getInputStream()))) {
|
||||
return reader.readAll();
|
||||
}
|
||||
}
|
||||
|
||||
public String analyzeSentiment(String text) {
|
||||
int mainSentiment = 0;
|
||||
int longest = 0;
|
||||
|
||||
Annotation annotation = pipeline.process(text);
|
||||
for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) {
|
||||
int sentiment = RNNCoreAnnotations.getPredictedClass(sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class));
|
||||
String partText = sentence.toString();
|
||||
|
||||
if (partText.length() > longest) {
|
||||
mainSentiment = sentiment;
|
||||
longest = partText.length();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert numeric sentiment to text
|
||||
return switch (mainSentiment) {
|
||||
case 0 -> "Very Negative";
|
||||
case 1 -> "Negative";
|
||||
case 2 -> "Neutral";
|
||||
case 3 -> "Positive";
|
||||
case 4 -> "Very Positive";
|
||||
default -> "Neutral";
|
||||
};
|
||||
}
|
||||
|
||||
public void generateReport(Map<String, Integer> sentimentCounts, int totalReviews) {
|
||||
System.out.println("\n=== Sentiment Analysis Report ===");
|
||||
System.out.printf("Total Reviews Analyzed: %d\n\n", totalReviews);
|
||||
|
||||
System.out.println("Sentiment Distribution:");
|
||||
for (Map.Entry<String, Integer> entry : sentimentCounts.entrySet()) {
|
||||
double percentage = (entry.getValue() * 100.0) / totalReviews;
|
||||
System.out.printf("%-12s: %2d reviews (%5.1f%%) %s\n",
|
||||
entry.getKey(),
|
||||
entry.getValue(),
|
||||
percentage,
|
||||
generateBar(percentage));
|
||||
}
|
||||
}
|
||||
|
||||
private static String generateBar(double percentage) {
|
||||
int bars = (int) (percentage / 5);
|
||||
return "[" + new String(new char[bars]).replace("\0", "=") + "]";
|
||||
}
|
||||
|
||||
private static String shortenText(String text, int maxLength) {
|
||||
return text.length() > maxLength ? text.substring(0, maxLength - 3) + "..." : text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
spring.application.name=senti
|
||||
11
SentimentAnalysisLab/src/main/resources/product_reviews.csv
Normal file
11
SentimentAnalysisLab/src/main/resources/product_reviews.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
review_id,review_text
|
||||
1,"This product is absolutely amazing! Works perfectly."
|
||||
2,"Terrible quality. Broke after 2 days of use."
|
||||
3,"Good value for the price. Very satisfied."
|
||||
4,"Not what I expected. Poor packaging."
|
||||
5,"Excellent customer service and fast shipping."
|
||||
6,"The item arrived damaged. Very disappointed."
|
||||
7,"Works well but instructions could be better."
|
||||
8,"Best purchase I've made this year!"
|
||||
9,"Overpriced for what you get."
|
||||
10,"Highly recommend this to all my friends."
|
||||
|
@@ -8,3 +8,4 @@ include 'InventoryManagementSystem'
|
||||
include 'SmartClinicManagementSystem:app'
|
||||
include 'SoftwareDevChatbot'
|
||||
include 'RegressionPredictionLab'
|
||||
include 'SentimentAnalysisLab'
|
||||
Reference in New Issue
Block a user