unsmart / extra_data /music-analyzer.livemd
beercan's picture
Create music-analyzer.livemd
54e8b9f verified
raw
history blame
5.7 kB
<!-- livebook:{"app_settings":{"access_type":"private","output_type":"rich","slug":"80s-music"},"file_entries":[{"file":{"file_system_id":"local","file_system_type":"local","path":"80s_detailed.csv"},"name":"80s_detailed.csv","type":"file"}],"persist_outputs":true} -->
# 1980s Music Sentiment
```elixir
Mix.install(
[
{:bumblebee, "~> 0.4.2"},
{:nx, "~> 0.6.1"},
{:exla, "~> 0.6.1"},
{:axon, "~> 0.6.0"},
{:kino, "~> 0.12.3"},
{:kino_explorer, "~> 0.1.18"},
{:kino_vega_lite, "~> 0.1.10"}
],
config: [nx: [default_backend: EXLA.Backend]]
)
Nx.global_default_backend(EXLA.Backend)
```
## Introduction
Music of the 80s came in many flavours; rock, pop, punk, synth. In this livebook we will delve into the feelings that many of these songs evoke. To our help we have [Hugging Face](https://huggingface.co/) and its library of open source ML models.
The model we will use here is a derivative of `roberta` called [`roberta-base-go_emotions`](https://huggingface.co/SamLowe/roberta-base-go_emotions?text=White+man+came+across+the+sea%2C+He+brought+us+pain+and+misery.+He+killed+our+tribes+killed+our+creed%2C+He+took+our+game+for+his+own+need). This model comes with 28 emotion labels. We will be able to use it via [Bumblebee Text Classification](https://hexdocs.pm/bumblebee/Bumblebee.Text.html#text_classification/3).
The idea is to pass a 1980's lyric into the model and get a classification back from it.
## Load models
```elixir
{:ok, emotions} = Bumblebee.load_model({:hf, "SamLowe/roberta-base-go_emotions"})
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, "SamLowe/roberta-base-go_emotions"})
:ok
```
<!-- livebook:{"output":true} -->
```
07:59:01.614 [info] TfrtCpuClient created.
```
<!-- livebook:{"output":true} -->
```
:ok
```
With the emotion sentiment model loaded, lets get some lyrics to analyze.
```elixir
text_input =
Kino.Input.textarea("Text",
default:
"White man came across the sea, He brought us pain and misery. He killed our tribes killed our creed, He took our game for his own need"
)
```
```elixir
text = Kino.Input.read(text_input)
serving = Bumblebee.Text.text_classification(emotions, tokenizer)
Nx.Serving.run(serving, text)
```
<!-- livebook:{"output":true} -->
```
%{
predictions: [
%{label: "neutral", score: 0.31277623772621155},
%{label: "optimism", score: 0.23790912330150604},
%{label: "caring", score: 0.2258605808019638},
%{label: "approval", score: 0.11500591784715652},
%{label: "desire", score: 0.030266664922237396}
]
}
```
### Load and parse a file
We have an attachment to this Livebook: `80s_detailed.csv`. We import it with Kino and use Kino Explorer to parse the csv into a dataframe, `df`.
```elixir
df =
Kino.FS.file_path("80s_detailed.csv")
|> Explorer.DataFrame.from_csv!()
```
```elixir
analysis = fn lyric ->
%{predictions: [%{label: label} | _tail]} = Nx.Serving.run(serving, lyric)
label
end
size = Explorer.Series.size(df["lyrics"])
lyrics_list = Explorer.Series.to_list(df["lyrics"])
take_num = 10
# last_songs = lyrics_list |> Enum.slice(-take_num..-1)
analysed_list_0_10 =
lyrics_list
|> Enum.take(take_num)
|> Enum.map(fn lyric -> analysis.(lyric) end)
# |> Enum.take(take_num)
# dummy_values =
# 1..(size - take_num)
# |> Enum.map(fn _ -> nil end)
# list = dummy_values ++ analysed_list
# updated_list = Explorer.DataFrame.put(
# df,
# :emotion,
# Explorer.Series.from_list(list)
# )
```
<!-- livebook:{"output":true} -->
```
["love", "desire", "neutral", "love", "neutral", "neutral", "neutral", "neutral", "curiosity",
"neutral"]
```
```elixir
analysed_list_121_130 =
lyrics_list
|> Enum.slice(121..130)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```
```elixir
analysed_list_11_30 =
lyrics_list
|> Enum.slice(11..30)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```
<!-- livebook:{"output":true} -->
```
["love", "neutral", "love", "love", "love", "disapproval", "joy", "neutral", "love", "love",
"neutral", "love", "neutral", "neutral", "love", "love", "desire", "love", "approval", "neutral"]
```
```elixir
analysed_list_31_60 =
lyrics_list
|> Enum.slice(31..60)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```
<!-- livebook:{"output":true} -->
```
["neutral", "disapproval", "neutral", "love", "love", "neutral", "love", "neutral", "love", "love",
"neutral", "curiosity", "love", "neutral", "admiration", "neutral", "neutral", "neutral", "love",
"neutral", "neutral", "neutral", "neutral", "neutral", "neutral", "neutral", "neutral", "neutral",
"fear", "neutral"]
```
```elixir
analysed_list_61_90 =
lyrics_list
|> Enum.slice(61..90)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```
<!-- livebook:{"output":true} -->
```
["joy", "neutral", "neutral", "love", "neutral", "neutral", "sadness", "love", "love", "neutral",
"neutral", "neutral", "amusement", "confusion", "sadness", "neutral", "love", "excitement",
"neutral", "neutral", "love", "desire", "neutral", "disappointment", "desire", "approval", "love",
"neutral", "love", "sadness"]
```
```elixir
analysed_list_91_120 =
lyrics_list
|> Enum.slice(91..120)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```
<!-- livebook:{"output":true} -->
```
["love", "joy", "neutral", "neutral", "love", "love", "neutral", "neutral", "love", "neutral",
"love", "neutral", "neutral", "neutral", "neutral", "love", "neutral", "neutral", "love",
"neutral", "disapproval", "neutral", "neutral", "desire", "neutral", "neutral", "love", "optimism",
"desire", "love"]
```
```elixir
analysed_list_131_150 =
lyrics_list
|> Enum.slice(131..150)
|> Enum.map(fn lyric -> analysis.(lyric) end)
```