For today’s article, I decided to take another look into speech recognition. But, this time will be a little different. I heard about an interesting machine learning technique called Sentiment Analysis. That’s something used to determine the tone of a block of text (such as positive, negative, and neutral), or in this case a recording of reading text. If you’ve never heard of Sentiment Analysis, I hadn’t either before I stumbled on it in the documentation. That’s why I thought it would be interesting to try. However, Sentiment Analysis can be very complex. Luckily for us, AssemblyAI makes it very simple, as we will see in this article.
As to not copy other projects, I wanted to move away from note cards and video editing to go towards a new project. When I learned about what Sentiment Analysis does, I knew I would want to read through reviews to see if products are good or not. Yes, there is a star system, but sometimes reviews and their stars can be misleading, such as people who give lower stars for great products or those who use neutral stars for bad products. Machine learning for Sentiment Analysis can be very difficult, as there are many different factors or challenges to consider. However, using the same API as I have been, creating a project with Sentiment Analysis was much easier, as I did not have to build from scratch.
In this article, I’m going to describe what Sentiment Analysis is, give a few use cases for when it should be used, and finally show the project I created to practice. So, without any delay, let’s look at what Sentiment Analysis is.
Sentiment Analysis is another branch of machine learning used to determine whether a sentence, or block of text, is positive, negative, or neutral. This type of analysis uses contextual mining that determines the social sentiment of what a block of text is trying to convey. Although its goal is to find the polarity of text (meaning positive, negative, or neutral), Sentiment Analysis also tries to decode the emotion behind the text, such as happiness, sadness, or anger. To do this, it uses different NLP (Natural Language Processing) algorithms.
3 Types of Sentiment Analysis
One type of Sentiment Analysis is emotion detection (also known as a lexicon method), which is used to determine the emotions behind text such as happiness, anger, sadness, and so on.
Another type is multilingual Sentiment Analysis, which looks for the positive, negative, or neutral tone to text in different languages. This is one of the more complex and challenging types of Sentiment Analysis.
The third type is aspect-based Sentiment Analysis, which focuses on an aspect. Features on a phone, for example, may include the battery, the camera quality, and so on.
The final type we will look at is fine-grained Sentiment Analysis, which rates the polarity of text on a scale. For example, the star rating system. It would determine if a block of text is very positive, as a rating of 5, neutral as a rating of 3, or negative as a rating of 1. The 2 or 4 would be only somewhat negative or positive respectively.
3 Approaches to Sentiment Analysis
There are also three approaches you could take to Sentimental Analysis. The first is the rule-based approach. This takes the lexicon method, tokenization, or parsing. After every word in the block of text is evaluated as positive or negative, it adds both values and compares. If there are more positive words than negative, the text block is presumed to be positive or vice-versa.
The second approach to Sentimental Analysis is using the automatic approach. This works more on the technique of machine learning by using predictive analysis.
Then, the automatic approach uses the extraction of the words. You could also use a Hybrid approach, which would be a combination of the two approaches, which helps raise the accuracy.
Using Sentiment Analysis
Sentiment Analysis is used to structure data in an efficient and cost-friendly manner. It is also used to solve real-time issues or to determine what to do in real-time scenarios. However, there are challenges to Sentiment Analysis. One challenge is comparing a neutral statement, as it may take more practice and understanding from the machine to not misclassify as positive or negative.
The next challenge is that tone may also be difficult to detect, such as if a person is optimistic or pessimistic. Along with tone, sarcastic or ironic comments are also difficult to detect. Finally, when people use image reactions, such as emojis or emoticons, you would also need to determine whether the emoji is good or bad.
There are many reasons you may want to use Sentiment Analysis, but let’s cover just a few. One reason would be for social media monitoring. This case is for finding honest opinions about products, services, or businesses.
Social media monitoring could also be used for brand monitoring, where companies follow what their customers are saying. Or for campaign monitoring, where candidates could track what the audience feels about their message. It could even be used for stock marketing monitoring, to get a sense of people’s attitudes towards new brands or products, and therefore make a decision on what may be a good investment.
In a way, it could be used even for compliance monitoring, to see if employees speak highly of benefits or even if they speak poorly of work conditions. That’s also good for if you’re thinking of a new job, to determine if the environment is for you before you interview. Just like a brand, it could be used to monitor reputation, so not only is it for companies or products but individuals as well.
Another use for Sentiment Analysis would be for customer support. So that there are not too many eyes on large volumes of incidents, Sentiment Analysis could be used to determine the priority of tickets. It could also be used to sort based on negative text or even to sort based on common issues.
Sentiment Analysis doesn’t have to only look at your company or product. It could also be used to research competitors or the market. If a company’s competitor receives positive comments for certain products or actions, it could be a sign to make a similar move. In the same way, if people react strongly in a negative way to certain products you are researching, making that type of product may be a risk.
Now that we know a little more about why to use Sentiment Analysis, it’s time for a little demonstration.
Coding out a machine learning program to conduct Sentiment Analysis is not very beginner-friendly. Fortunately for us, there is an easier way using AssemblyAI’s speech recognition API. In a previous article, I explained how to upload audio files, submit the audio for transcription, and get the transcribed text back. Because I’ve talked about how to do all of this in detail before, I will only briefly cover each basic function used. With that, we’re ready to begin.
To get started, we need to create a file called speech_to_text.py. This file will contain a class with all of our necessary functions. As always, the first function is the initializer. The second will be needed to upload the file, where we just call an endpoint to upload to AssemblyAI.
Next, there is a function to submit the audio. In the JSON for this function, we will add the option to allow “sentiment_analysis”, essentially by setting the response to true. After this, the get_text function will find the transcript and return the response.
Finally, the upload_file function uses __read_file, which we will declare last. The __read_file function simply opens the file and reads it in chunks. The code will look like this:
class speech_to_text:
"""
"""
def __init__(self, api_key):
self.endpoint = "https://api.assemblyai.com/v2/"
self.header = {
"authorization": api_key
}
def upload_file(self, file):
response = requests.post(f"{self.endpoint}upload", headers=self.header, data=self.__read_file(file))
return response.json()
def submit_audio(self, uploaded_file):
self.header["content-type"] = "application/json"
json = {
"audio_url": uploaded_file,
"punctuate": True,
"format_text": True,
"auto_chapters": True,
"sentiment_analysis": True
}
url = f"{self.endpoint}transcript"
response = requests.post(url, json=json, headers=self.header)
return response.json()
def get_text(self, transcript_id):
url = f"{self.endpoint}transcript/{transcript_id}"
response = requests.get(url, headers=self.header)
return response.json()
def __read_file(self, filename, chunk_size=5242880):
print(filename)
with open(filename, 'rb') as file:
while True:
data = file.read(chunk_size)
if not data:
break
yield data
The second file we will need is to test the file to call the class we just created. In this file, we need to import the class, also the time library, call the class using your API key, and call each function to upload, submit, and get the text. We will also check if there is an error before printing the results:
from speech_to_text import *
import time
file = "<PATH_TO_FILE>"
converter = speech_to_text("<YOUR_API_KEY>")
upload = converter.upload_file(file)
video_file = converter.submit_audio(upload["upload_url"])
time.sleep(30)
analysis = converter.get_text(video_file["id"])
if analysis["status"] != "error":
print(analysis)
else:
print("Error getting sentiment analysis.")
Finally, we’re ready to test. I recorded an audio file where I read a few product reviews on Amazon. The file ended up being just over six minutes long, so naturally, the response was very lengthy. To make it more readable, I will only show the portion of the output that displays the Sentiment Analysis results:
'sentiment_analysis_results': [{'text': "Hey guys, what's up?", 'start': 790, 'end': 1542, 'sentiment': 'NEUTRAL', 'confidence': 0.7341238260269165, 'speaker': None}, {'text': 'This is Mike from Mike Tech game.', 'start': 1556, 'end': 3320, 'sentiment': 'NEUTRAL', 'confidence': 0.882032036781311, 'speaker': None}, {'text': "So today I'm going to be testing out assembly AI sentiment analysis feature.", 'start': 3650, 'end': 10230, 'sentiment': 'NEUTRAL', 'confidence': 0.8951022028923035, 'speaker': None}, {'text': "So to do this I need some data and I'll be using this audio profile as that data that I'll be uploading to their site.", 'start': 11270, 'end': 19940, 'sentiment': 'NEUTRAL', 'confidence': 0.910209059715271, 'speaker': None}, {'text': "The day I'm going to use specifically is some Amazon product reviews.", 'start': 21470, 'end': 26550, 'sentiment': 'NEUTRAL', 'confidence': 0.5865017771720886, 'speaker': None}, {'text': "Basically just some random products that I kind of found throughout Amazon and we're going to give it a try and see what happens.", 'start': 27350, 'end': 36198, 'sentiment': 'POSITIVE', 'confidence': 0.5467420816421509, 'speaker': None}, {'text': 'So this first review is for a Star Tech USB 3.0 ECA adapter.', 'start': 36284, 'end': 45390, 'sentiment': 'NEUTRAL', 'confidence': 0.9124034643173218, 'speaker': None}, {'text': "So let's see what they have to say.", 'start': 47730, 'end': 49920, 'sentiment': 'NEUTRAL', 'confidence': 0.7884692549705505, 'speaker': None}, {'text': 'So and so it says have an older thermal Take Theta dock running USB 2.0, but it also has an Ecada interface.', 'start': 51270, 'end': 59290, 'sentiment': 'NEUTRAL', 'confidence': 0.8681536912918091, 'speaker': None}, {'text': 'Shows some overhead from the Ecada USB 30 conversion, but happy great results.', 'start': 60690, 'end': 67690, 'sentiment': 'POSITIVE', 'confidence': 0.9396385550498962, 'speaker': None}, {'text': "Another user said quality cable but didn't work for my purposes.", 'start': 69930, 'end': 74830, 'sentiment': 'NEGATIVE', 'confidence': 0.8167780041694641, 'speaker': None}, {'text': 'Another user breathed new life into Eseta USB 20 combo drive cases but not compatible with some enclosures.', 'start': 78790, 'end': 86990, 'sentiment': 'NEUTRAL', 'confidence': 0.5507873296737671, 'speaker': None}, {'text': "Let's go further down.", 'start': 88810, 'end': 91120, 'sentiment': 'NEGATIVE', 'confidence': 0.5018455386161804, 'speaker': None}, {'text': 'This person said this was a great purchase.', 'start': 92530, 'end': 95442, 'sentiment': 'POSITIVE', 'confidence': 0.9386810660362244, 'speaker': None}, {'text': 'No fuss and no bother with configuring anything.', 'start': 95586, 'end': 98498, 'sentiment': 'NEUTRAL', 'confidence': 0.6314108967781067, 'speaker': None}, {'text': 'You simply take the cable out of the bag and plug everything in.', 'start': 98584, 'end': 101594, 'sentiment': 'NEUTRAL', 'confidence': 0.8211394548416138, 'speaker': None}, {'text': "It's that simple.", 'start': 101632, 'end': 102700, 'sentiment': 'POSITIVE', 'confidence': 0.46939191222190857, 'speaker': None}, {'text': 'This is from another person cable is of good quality.', 'start': 106610, 'end': 110060, 'sentiment': 'POSITIVE', 'confidence': 0.6366212368011475, 'speaker': None}, {'text': 'However, I bought this to use with a four Bay array enclosure which only had an e stated connection.', 'start': 111230, 'end': 117210, 'sentiment': 'NEUTRAL', 'confidence': 0.8613907098770142, 'speaker': None}, {'text': 'This other person from the UK said very good performance used with a desktop computer with USB 3.0.', 'start': 118370, 'end': 125780, 'sentiment': 'POSITIVE', 'confidence': 0.9508991837501526, 'speaker': None}, {'text': 'All right, so these were some good to medium reviews.', 'start': 126950, 'end': 132586, 'sentiment': 'POSITIVE', 'confidence': 0.89154052734375, 'speaker': None}, {'text': "Let's give it a try with some of the bad reviews just so we can see if we can kind of trigger that negative aspect of the sentiment analysis.", 'start': 132778, 'end': 146130, 'sentiment': 'NEGATIVE', 'confidence': 0.5098620653152466, 'speaker': None}, {'text': 'So this person gave it a one star review.', 'start': 146570, 'end': 148770, 'sentiment': 'NEUTRAL', 'confidence': 0.6283271312713623, 'speaker': None}, {'text': 'It was slow.', 'start': 148940, 'end': 149770, 'sentiment': 'NEGATIVE', 'confidence': 0.5421875715255737, 'speaker': None}, {'text': 'You think USB 3.0 interfacing with usage would be faster than USB two?', 'start': 149830, 'end': 154220, 'sentiment': 'NEUTRAL', 'confidence': 0.7479754090309143, 'speaker': None}, {'text': 'I hoped it would be a lower cost solution of speeding my external Http data transfer up than buying an Eseta PCIe card and an Eseta cable.', 'start': 155330, 'end': 167074, 'sentiment': 'NEUTRAL', 'confidence': 0.5160191059112549, 'speaker': None}, {'text': "But it wasn't.", 'start': 167122, 'end': 168150, 'sentiment': 'NEUTRAL', 'confidence': 0.5051068663597107, 'speaker': None}, {'text': 'This person from the United States said does not work at all.', 'start': 169130, 'end': 172820, 'sentiment': 'NEGATIVE', 'confidence': 0.9428792595863342, 'speaker': None}, {'text': "This other person from the US said just don't the communication from the device of the computer will not work.", 'start': 176010, 'end': 181858, 'sentiment': 'NEGATIVE', 'confidence': 0.8240898847579956, 'speaker': None}, {'text': 'Spend more money and buy a motherboard add on.', 'start': 181944, 'end': 184620, 'sentiment': 'NEUTRAL', 'confidence': 0.5805968046188354, 'speaker': None}, {'text': "Let's see, we can't find something else here.", 'start': 187870, 'end': 192700, 'sentiment': 'NEUTRAL', 'confidence': 0.6683025360107422, 'speaker': None}, {'text': "Another person from the US couldn't get to work between a computer with an academic four terabyte external hard drive with its own AC power adapter.", 'start': 195910, 'end': 205370, 'sentiment': 'NEGATIVE', 'confidence': 0.7493458986282349, 'speaker': None}, {'text': 'And somebody just has a post that says one star did not work.', 'start': 206770, 'end': 212020, 'sentiment': 'NEGATIVE', 'confidence': 0.7950200438499451, 'speaker': None}, {'text': "All right, so let's try out another product.", 'start': 213250, 'end': 217480, 'sentiment': 'NEUTRAL', 'confidence': 0.593720555305481, 'speaker': None}, {'text': 'This is official Arduino Starter kit.', 'start': 220730, 'end': 224010, 'sentiment': 'NEUTRAL', 'confidence': 0.5788508653640747, 'speaker': None}, {'text': 'So the person from the US says this kit is awesome.', 'start': 225710, 'end': 232620, 'sentiment': 'POSITIVE', 'confidence': 0.9685182571411133, 'speaker': None}, {'text': 'Kind of.', 'start': 232950, 'end': 233940, 'sentiment': 'NEUTRAL', 'confidence': 0.6421152949333191, 'speaker': None}, {'text': 'Another person said all the basics plus fun.', 'start': 238870, 'end': 241660, 'sentiment': 'POSITIVE', 'confidence': 0.5885667204856873, 'speaker': None}, {'text': "Another person didn't have as good an experience.", 'start': 243490, 'end': 246122, 'sentiment': 'NEGATIVE', 'confidence': 0.6503105759620667, 'speaker': None}, {'text': 'Not exactly as described.', 'start': 246316, 'end': 248630, 'sentiment': 'NEGATIVE', 'confidence': 0.7352493405342102, 'speaker': None}, {'text': 'They ordered ten kits for their students.', 'start': 250270, 'end': 252350, 'sentiment': 'NEUTRAL', 'confidence': 0.8988600969314575, 'speaker': None}, {'text': 'Received four kits.', 'start': 252460, 'end': 253970, 'sentiment': 'NEUTRAL', 'confidence': 0.8394066095352173, 'speaker': None}, {'text': "Another person says does what it says but it's overpriced.", 'start': 259370, 'end': 263070, 'sentiment': 'NEGATIVE', 'confidence': 0.7123470306396484, 'speaker': None}, {'text': "Let's see if we can find some of the bad reviews so let's go up to the one stars open the first package and box looks worn open it up and all the boxes inside were extremely dirty.", 'start': 269910, 'end': 300034, 'sentiment': 'NEGATIVE', 'confidence': 0.8238954544067383, 'speaker': None}, {'text': 'The wooden board that comes with the kit was already broken apart and burnt to hell very displeased and submitted an exchange immediately.', 'start': 300082, 'end': 307890, 'sentiment': 'NEGATIVE', 'confidence': 0.9628779292106628, 'speaker': None}, {'text': 'Again it took several days to get the exchange since the craziness in the world the box from the other person said the box from the first purchase arrived with torn on all corners like someone had it carefully opened but without damaging the plastic steel slash tape.', 'start': 308330, 'end': 328510, 'sentiment': 'NEUTRAL', 'confidence': 0.4840307831764221, 'speaker': None}, {'text': "I thought it just get a replacement replacement arrived the same way looks like the boxes tampered with but I did not want to write a review until I read reviews from others looks like it's not just me another person called it price gouging this other person from the US said waste of money.", 'start': 328830, 'end': 352206, 'sentiment': 'NEGATIVE', 'confidence': 0.8741855621337891, 'speaker': None}, {'text': "The book is unreadable with pale text on pale background but the online version is readable the resistors are unusable unless you have your own multimeter to check resistance another person said I would only recommend this to a beginner if they found absolutely no alternative options after researching resources simply said never worked so looks like we're now at about the six minute and 25 second Mark so I think that should be a decent amount of data.", 'start': 352268, 'end': 391430, 'sentiment': 'NEGATIVE', 'confidence': 0.6042648553848267, 'speaker': None}, {'text': "We'll see how it goes but you have a great day guys.", 'start': 391480, 'end': 394940, 'sentiment': 'POSITIVE', 'confidence': 0.9566168785095215, 'speaker': None}], 'entity_detection': False, 'entities': None}
In today’s article, we took a deep dive into Sentiment Analysis. First, we described what Sentiment Analysis is. Next, we looked at a few use cases. Finally, I demonstrated a way to analyze the sentiment of product reviews using AssemblyAI’s API. I found it interesting to learn that machine learning could detect the tone of the text, and assign a positive, negative, or neutral value to it.
From what I could see, the analysis was fairly accurate, and I was pleasantly surprised by how well the analysis picked up on neutral responses. Overall, I thought it was an interesting project and I learned a lot. Hopefully, it was interesting for you as well. Until next time, cheers!
References: