파이썬
노션에 알고리즘 공부 내역을 정리해두었다. 틀린이유, 새롭게 알게 된 점, 등이 적혀있다.
[백준]
https://www.notion.so/9e203ae0d4e44766be5b1cd9436d2f7a?pvs=4
[프로그래머스]
https://www.notion.so/59cf9a2ff0014a70b38b65f4f3bf7144?pvs=4
노션에 알고리즘 공부 내역을 정리해두었다. 틀린이유, 새롭게 알게 된 점, 등이 적혀있다.
[백준]
https://www.notion.so/9e203ae0d4e44766be5b1cd9436d2f7a?pvs=4
[프로그래머스]
https://www.notion.so/59cf9a2ff0014a70b38b65f4f3bf7144?pvs=4
한국정보과학회 KCC 2020 투고, 2021 포스터 발표 및 시상
선형회귀 기법을 사용
그래프 시각화를 중시함
인구수 변화율 모델 설립
<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>

firebase web 개발, firebase storage sdk를 사용했다

음성 데이터 다중 감성 분류기를 통해 분류하였다.
위 사진은 '슬픔'으로 판단된 감성을 저장한 firebase storage 모습이다.

중립음악의 경우, 분류기의 결과가 '중립'이다.
위 사진은 '중립'으로 판단된 로파이 장르의 음악을 저장한 firebase storage 모습이다.

firebase realtime database를 사용하여 메타데이터를 저장했다.
디렉토리를 통해 top-down 방식으로 음악 위치를 찾을 수 있다.
감성음악/기쁨/001 의 value로 001.mp3의 위치를 반환한다.
https://romeoh.tistory.com/entry/Firebase-Python-Firebase-Realtime-Database

python으로 개발하기 위해 flask를 사용했다.

firebase hosting sdk를 사용해 배포했다.


postman을 사용하여 params와 body request에 대한 api 작동을 확인했다.

flask, firebase 관련 라이브러리를 import 한다.
firebase sdk를 사용하기 위해 initialize 과정을 거친다.
이 값들은 공개해서는 안된다.

코드의 가장 하단에는 위와 같은 모습이다.
app.run을 통해 대기중인 모습이다.



genre, mode, prediction을 바탕으로 firebase realtime db에서
우리가 원하는 음악의 메타데이터를 가져오는 함수이다.
mode에 따라 3가지로 구분하였으며,
mode2의 경우, 감성음악과 중립음악이 교차적으로 등장할 수 있도록 구성하였다.


앞 단계에서 얻은 음악 메타데이터를 사용하는 함수이다.
재생할 음악의 위치가 담긴 리스트를 구성함으로써,
재생목록 playlist(json)를 만들 수 있었다.

재생할 음악 위치가 담긴 jsonfile을 바탕으로 스트리밍하는 함수이다.
audio/mp3타입으로 반환하며, 현재 곡 종료 후 다음 곡을 자동으로 재생한다.
| request value | 의미 | 사용처 |
| genreId | 음악 장르(=genre) | query를 위한 조건문(if,elif,else) 속 조건 |
| modeId | 재생모드(예민도) | query를 위한 조건문(if,elif,else) 속 조건 |
1. 가장먼저 root url에 의해, genreId, modeId가 생성된 상태에서, 진행된다.
2. nlp 모델결과로 감성prediction을 얻는다.
3. get_genre 함수에서 메타데이터를 얻는다.
4. get_playlist 함수에서 플레이리스트를 얻는다.
5. stream_audio 함수에서 음악을 재생한다.
저자는 firebase, flask를 이용한 api를 개발하려고 했지만, api 배포에 실패하였다.
원인은 firebase hosting에 있었으며, 독자들에게 fibase를 통한 api배포를 추천하지 않는다.
두번째로 시도한 것이 nodejs, aws, filezilla, putty, sql을 이용한 api개발이다.
연동해야 할 기술이 많아 더 복잡하지만, 한번 익히면 그 이후에는 쉬운 방법이다.
api 배포시 방화벽에 막혔는데, 저자는 방화벽을 뚫었지만, 이것이 싫다면, 보안 설정을 잘 하는 것이 좋다.
| [서버] 딥러닝-mysql 연동하는 aws 서버 (0) | 2023.05.12 |
|---|---|
| [딥러닝] 음성 데이터 다중 감성 분류 (audio data multi-emotion classification) (0) | 2022.11.19 |
<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>

firebase web 개발, firebase storage sdk를 사용했다

음성 데이터 다중 감성 분류기를 통해 분류하였다.
위 사진은 '슬픔'으로 판단된 감성을 저장한 firebase storage 모습이다.

중립음악의 경우, 분류기의 결과가 '중립'이다.
위 사진은 '중립'으로 판단된 로파이 장르의 음악을 저장한 firebase storage 모습이다.
https://poiemaweb.com/nodejs-mysql
https://myinfrabox.tistory.com/213

위의 사이트를 참고하여 mysql을 연동하였다.


test relation은 다음과 같은 구조(schema)를 가진다.
| type | emotion | name | locate | genre |
| int | varchar | varchar | varchar | varchar |

aws ec2를 사용하여 api를 배포했다.
무료티어를 사용했으며, ubuntu 개발로 설정했다.
보안 그룹은 다음과 같다.
nodejs 코드는 3001포트에서 실행되며, ssh는 22포트에서 실행하도록 설정했다.



putty ubuntu를 사용했다.
hostname, port number, SSH-auth를 입력해주면 된다.
이때, hostname은 개발 인스턴스의 public ipv4,
port number은 앞서 언급했던 22,
SSH-auth은 인스턴스 생성시 사용했던 private key를 넣어준다.


filezilla를 통해 코드 파일을 전송했다.
이때 호스트명을 인스턴스의 public ipv4로 설정해야 한다.
https://copycoding.tistory.com/424
위 사이트를 참고했다


postman을 사용하여 params와 body request에 대한 api 작동을 확인했다.

require을 통해 필요한 라이브러리를 불러왔다.
express는 app을 위해, child_process는 nlp코드 연동을 위해,
body-parser는 body request를 받기 위해 불러왔다.
port=3001로, aws 설정 포트와 맞췄다.

코드의 가장 하단에는 위와 같은 모습이다.
app.listen을 통해 대기중인 모습이다.
api를 app이라는 이름의 module로 저장했다.

datatext를 process.py(nlp모델) 의 input 값으로 줬을때, 그 결과값(print문)을 저장하는 코드이다.
이때, getemotion코드는 async function으로 정의해야 한다.
또한 이 전체 코드를 async func를 처리하기 위해 Promise로 묶었다.
spawn을 통해 python 컴파일을 실행했고, 'close', 'error'문을 작성하여,
컴파일 성공과 실패에 대한 핸들링 로직을 만들었다.
예측 결과는 prediction에 저장했다.

request params, body를 받아와야 한다.
root url에 대한 코드를 작성함으로써, 항상 초기에 실행되도록 만들었다.
genreId, modeId는 params이고, datatext는 body이다.
이때 genreId, modeId는 sql query를 위해 사용된다.
datatext는 3.1.의 딥러닝 모델 input으로 사용된다.
try catch문을 통해 datatext-딥러닝 모델 연동을 체크했다.
| request value | 의미 | 사용처 |
| genreId | 음악 장르(=genre) | sql query 속 attribute |
| modeId | 재생모드(예민도) | sql query를 위한 조건문(if,elif,else) 속 조건 |
| datatext | OCR 결과 텍스트 | nlp 모델의 input |



my sql와 연동하여, 음악 메타데이터를 반환하는 async func get_path 코드다.
이 코드를 async func를 처리하기 위해 Promise로 묶었다.
modeId에 따라 세가지 조건문으로 나뉜다.
if modeId=='1'
else if modeId=='3'
else
modeId가 1일때는 감성음악만을 재생해야 한다.
nlp모델 예측 결과인 prediction에 해당하는 emotion을 가진 row의 locate attribute를 가져와야 한다.
따라서 sql query를 다음과 같이 작성된다.
SELECT locate FROM test WHERE emotion='${prediction}
modeId가 3일때는 중립음악만을 재생해야 한다.
nlp예측 결과와 상관없이, 음악종류(type)이 2이고, emotion='중립' 을 가진 row의 locate attribute를 가져와야 한다.
또한 이때, 사용자가 설정한 취향 장르인 genre까지 고려해야 한다.
따라서 sql query를 다음과 같이 작성된다.
SELECT locate FROM test WHERE type='2' AND genre='${genreId}' AND emotion='중립'
modeId가 2일때는 감성+중립음악을 재생해야 한다.
감성음악은 prediction에 의존하고, 중립음악은 genreId에 의존한다.
두 조건을 or로 묶어서 사용했다.
따라서 sql query를 다음과 같이 작성된다.
SELECT locate FROM test WHERE emotion='${prediction}' or (emotion='중립' and genre='${genreId}'

최종적으로 음악 위치인 locate 데이터가 담긴 리스트가 반환된다.
path 리스트는 json 형식으로 변환했다.

/play url에 해당하는 코드이다.
async function으로 작성했다.
왜냐하면, 일부 함수가 async func이기 때문이다.
1. 가장먼저 root url에 의해, genreId, modeId, datatext가 생성된 상태에서, 진행된다.
2. getemotion 함수를 통해 nlp 모델결과로 감성prediction을 얻는다.
3. get_path 함수를 통해 sql 결과로 원하는 음악의 위치 데이터를 얻는다.
4. 테이블 형식(row)의 데이터를 형변환한다.
5. finalPath를 json형태로 반환하여 응답한다.

/emotion url에 해당하는 코드이다.
async function으로 작성했다.
왜냐하면, 일부 함수가 async func이기 때문이다.
1. 가장먼저 root url에 의해, genreId, modeId, datatext가 생성된 상태에서, 진행된다.
2. getemotion 함수를 통해 nlp 모델결과로 감성prediction을 얻는다.
3. prediction을 json형태로 반환하여 응답한다.
저자는 firebase, flask를 이용한 api를 개발하려고 했지만, api 배포에 실패하였다.
원인은 firebase hosting에 있었으며, 독자들에게 fibase를 통한 api배포를 추천하지 않는다.
두번째로 시도한 것이 nodejs, aws, filezilla, putty, sql을 이용한 api개발이다.
연동해야 할 기술이 많아 더 복잡하지만, 한번 익히면 그 이후에는 쉬운 방법이다.
api 배포시 방화벽에 막혔는데, 저자는 방화벽을 뚫었지만, 이것이 싫다면, 보안 설정을 잘 하는 것이 좋다.
| [서버] 딥러닝-flask-firebase 연동하는 서버 (0) | 2023.06.25 |
|---|---|
| [딥러닝] 음성 데이터 다중 감성 분류 (audio data multi-emotion classification) (0) | 2022.11.19 |
(https://89douner.tistory.com/256
https://koreapy.tistory.com/1376)

<SRGAN과의 차이점>
train, test의 통계가 다름 등등의 문제가 있었기에 Batch Normalization 제거, residual in residual dense block으로 연결
vgg loss만, 상대적으로 더 진짜인지가짜인지.
activation 이전의 feature map을 사용. sparse문제와 밝기복원 문제를 해결함.
<total loss>

<network interpolation>


본 논문에서는 SRGAN의 성능향상을 위해 크게 세가지를 바꿨습니다.
2.2.1. Batch Normalization Layer 제거
우선 SRGAN에서는 Batch Normalization 을 사용했었습니다. 하지만, training dataset과 test dataset의 statistics가 많이 달라서 오히려 BN을 사용하면 artifact 가 생기게 되고, 일반화 성능또한 저하된다고 합니다. 이는 range flexibility가 제거되기 때문인데요, 일반적으로 edge는 양쪽으로 밝기차가 많이납니다. 하지만 feature가 normalize 되면서 이러한 밝기의 범위도 좁아지기 때문에 smooth한 결과가 나옵니다. 또한, BN layer를 제거함으로써 computatianal complexity와 memory usage에서 많은 이점을 얻을 수 있습니다.

2.2.2. Dense connection

기존 SRResNet 구조는 그대로 가져가면서 Block만 교체했습니다. BN layer가 빠지고 단순히 Residual conntection을 사용한 것이 아닌 Dense connection(==fully connection)도 함께 사용했습니다.
2.3.1.Discriminator는 a가 b보다 진짜 같은지를 판단한다 (상댓값)

기존SRGAN의 판별자는 하나의 input 이미지(x)가 진짜이고 자연스러운 것일 확률을 추정했다. (절댓값)
relativistic discriminator는 실제 이미지(Xr)가 가짜 이미지(Xf) 보다 상대적으로 더 현실적일 확률을 예측한다. (상댓값)


2.4.1. activation 이전의 feature map을 사용한다
이전 논문(SRGAN)에서는 Perceptual loss를 VGG loss와 Gan loss를 통틀어서 Perceptual Loss라고 네이밍을 했는데, 이번 논문에서는 VGG loss만을 Perceptual loss라고 정했습니다. 기존에는 activation 이후의 feature map을 사용했지만 본 논문에서는 activation 이전의 feature map을 사용합니다.
<after activation의 문제> ---->>> <before activation으로 해결>


2.4.2.VGG loss만을 Perceptual loss로 취급한다

최종 loss 식에는 perceptual loss, RaGan loss, L1 loss가 사용되었습니다.
2.5.1.초기 가중치와 최종 가중치를 interpolation
아무래도 GAN 방식이다 보니 학습이 진행되면서 perceptual quality는 좋아져도 artifact가 생기는 문제가 발생합니다. 이를 해결하기위해 단순히 가중치를 곱해서 더하는 것 만으로 다음과 같은 결과를 얻을 수 있다고 합니다.




| [딥러닝][논문리뷰] SRGAN (0) | 2023.01.27 |
|---|
1.기존 SR모델들이 가진 texture detail이 떨어지는 문제 발생
2.loss function이 원인이었음.
3.mse based per-fixel loss는 3posed-problem이 있기 때문에, 즉 가능한 고해상도가 여러개이다. 이들을 평균내는 결과를 취하게 되므로, GAN이 생성한 다양한 high texture detail들이 smoothing 되는 결과를 초래했던 거였음
4.perceptual loss를 사용하자!
5.perceptual loss는 이미지를 vgg19를 통과시켜 얻은 feature map을 비교하는 것.
6.해결!!
Deep Learning-based method, 그 중에서도 2017년 공개된 논문( Photo-Realistic Single Image Super Resolution Using a Generative Adversarial Network)에서 처음 등장한 SR GAN

기존 SR 모델 중 하나인 SRResNet이 생성한 이미지를 매우 확대해보면, original HR image와 비교했을 때 texture detail이 떨어지는 것을 확인할 수 있습니다.
저자들은 이 원인이 기존 SR 모델들의 loss function에 있다고 보았습니다. 기존 SR 모델들의 목표는 보통 복구된 HR 이미지와 원본 이미지의 pixel 값을 비교하여 pixel-wise MSE를 최소화하는 것입니다. 그러나 pixel-wise loss를 사용하면 high texture detail을 제대로 잡아내지 못하는 한계가 있습니다. 저자들은 이전 연구와는 다르게 VGG network의 high-level feature map을 이용한 perceptual loss를 제시하여 이런 문제를 해결하였다고 합니다.

Generator을 이용해 얻어낸 가짜 고해상도 이미지를 진짜 고해상도 이미지와 Pixel by pixel로 비교하는 것을 Per-pixel loss라고 하고,각 이미지를 pre-trained CNN 모델에 통과시켜 얻어낸 feature map을 비교하는 것을 Perceptual loss라고 합니다.
동일한 이미지이나 한 pixel씩 오른쪽으로 밀려있는 두 이미지가 있다고 가정해보겠습니다. 이런 경우 loss는 0 이어야하겠지만 per-pixel loss를 구하면 절대 0이 될 수 없습니다. per-pixel loss의 이러한 단점은 super resolution의 고질적인 문제인 Ill-posed problem 때문에 더 부각됩니다.

Ill-posed problem이란 저해상도 이미지를 고해상도로 복원을 해야 하는데, 가능한 고해상도의 이미지가 여러 개 존재하는 것을 말합니다. GAN 모델을 이용하여 여러 개의 가능한 고해상도 이미지 (아래 그림상 Possible solutions)를 구하여도 MSE based Per-pixel loss를 사용하면 possible solutions 들을 평균내는 결과를 취하게 되므로, GAN이 생성한 다양한 high texture detail들이 smoothing 되는 결과를 초래합니다.

---> 이런 단점을 해결하기 위해 저자들은 GAN이 생성한 HR 이미지와 Original HR 이미지를 Pretrained VGG 19에 통과시켜 얻은 Feature map 사이의 Euclidean distance를 구하여 content loss를 구하였습니다.

2.4.1. content loss


GAN이 생성한 이미지와 Original 이미지를 VGG 19에 통과시켜 얻은 Feature map 사이의 Euclidean distance를 구한다
2.4.2. adversarial loss

Generator가 생성한 이미지를 진짜라고 판단할 확률로 앞에 - 가 붙어있으므로 이를 최소화하는 방향으로 학습한다

| [딥러닝][논문리뷰] ESRGAN (0) | 2023.01.27 |
|---|
<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>
http://www2.projects.science.uu.nl/memotion/emotifydata/
Dataset of emotional annotations
Description of the annotations The dataset consists of 400 song excerpts (1 minute long) in 4 genres (rock, classical, pop, electronic). The annotations were collected using GEMS scale (Geneva Emotional Music Scales) [1]. Each participant could select max
www2.projects.science.uu.nl

위 사이트에서 제공하는 4개의 음악장르(classical, pop, electronic, rock)별 각 100개의 음성 데이터파일을 사용했다.
우리의 타겟인 감성은 9가지로 분류되며(다중감성분류), 데이터 분포도를 확인해본 결과, 아래와 같은 불균형을 보였다.

데이터 불균형을 해결하기 위한 첫번째 시도는 유사한 특성끼리 묶는 것이다.

데이터 개수가 부족하기 때문에 undersampling이 아닌, oversampling을 수행해야 한다.
'sadness'에 해당하는 음성데이터에 관해 augmentation을 진행한다. 10개의 데이터만 추가하기로 결정했다.
(이에 대한 근거로는, 125:97=106:82 이기 때문에,...그냥 저자의 생각에 10개가 적당할 것 같았다.)
진행순서는 아래와 같다.

(load_audiofiles는 현재 cell보다 뒤에 정의된 함수라서 물결밑줄이 그어졌다)




음악 장르별 균등하게 학습될 수 있게 하기 위해 다음의 순서에 따라 진행했다.


음악 데이터를 불러오기 위해, librosa.load를 사용했다.
파일 경로와 sample_rate를 입력받으면, signal ( type: array) 을 반환하는 함수를 만들었다.



앞서 정의한 load_audiofiles를 바탕으로 멜로디 특성을 담기 위한 함수를 정의했다.
타켓은 역시나 '감성, feeling, emotion' 이다.
tag를 사용하여 train데이터에만 augmeted data를 추가한다.
shape을 확인했을 때, 320+10=330으로 제대로 추가됨을 확인했다.

target label이 str(문자열)이므로 LabelEncoder를 통해 int(정수)로 변환시킨다.


( https://ahnjg.tistory.com/93 링크를 참고하였다.)
음성 신호를 전처리하기 위해, 성능이 좋아 많은 이들이 사용하는,
fourier transform + mel-filter = melspectrogram 을 사용했다.
사람의 청각기관을 반영했다는 특징역시 선택이유 중 하나이다.
melspectrogram을 통해 음성데이터를 변환해준다.

mel_train, me_val 을 standardscaler로 정규화하고, (개수, 1, height, width)의 크기를 얻었다.
train 데이터 개수가 적기 때문에 과적합 가능성이 크다. 따라서 두가지 방법을 시도했다.
1. dropout
2. 적은 layer



cnn layer (4 layer, convolution) 를 직접 쌓았다.
음성데이터이기 때문에 층을 너무 작지 않거나 크기않게 4개로 설정했다.
relu 활성화함수를 사용했고, 마지막에는 softmax를 사용했다.
각 합성곱이 끝날때마다 dropout, batchnormalization을 했다.
또한 4개의 다중감성 분류이므로, num_emotions=4로 설정했다.

SGD optimizer를 사용했으며, learning rate=0.01, momentum=0.9로 설정했다.
출력속도를 높이기 위해 epochs=10으로 설정했으니, 데이터양과 시간이 충분한 사람은
epochs=64로 수정하는 것을 권한다.

loss는 crossentropyloss를 사용했다.

accuracy_score을 확인했을 때, 'y_true == y_pred'이라는 문구가 출력되었다. validation data에 관해 정확한 예측을 수행하였음을 확인했다.
loss 그래프를 그려본 결과, epoch가 진행함에도 변화하지 않았다.
즉, 초기에 학습이 모두 완료가 된다는 뜻이므로, 데이터 개수가 너무 적어서 발생한 문제같다...
그래도 혹시 모르니까, 파라미터를 바꿔가면서 결과값을 확인해봤다. (3.2.에서 진행함)

inverse_transform을 사용하여 label encdoing 역변환하였을때, validiation data 예측은 위와 같은 결과를 보인다.

SGD 대신 ADAM optimizer를 사용했고, learning rate=0.0001로 설정했다.
이외의 파라미터는 동일하다.

이번에도 loss가 상수함수의 꼴을 나타냈다. (즉, y_pred==y)

( 예측결과에 차이가 있는 것은 train, test 분리가 다르게 되었기 때문이다. )
데이터개수 부족으로 인해, 신경망 초기에서 모든 학슴이 완료되는 것으로 확인되었다.
또한, 결과가 너무 좋게 나왔다.
모델 자체는 문제가 없어 보였으므로, 앞으로도 모델1,2 + alpha 를 사용하여 진행할 생각이다.
https://www.sellbuymusic.com/search/freebgm
음악 태그를 바탕으로 label을 붙어서 데이터를 수집중에 있다.

sample audio data (.wav)를 다운받아서 진행했다.
이 파일은 기차의 휘슬소리로, 크게 2번 경적을 울린다.

fade out 함수를 만들어준다.
멜로디(주파수), 음압에 대해 각각 fade 효과를 적용해야 한다.
따라서, 입력받은 2차원 데이터를 각각 1차원 데이터로 처리하여(인덱싱) 선형연산을 해준다.
시간이 지날수록 소리가 작아져야 하기때문에, 점진적으로 작아지는 가중치를 곱해줘야 한다.
이를 위해 np.linspace(1.0,2.0, length)를 사용했다.




4.3. 그래프 그리기에 정의한 함수를 바탕으로 결과를 출력해본 결과이다.
사진과 같이 fade-out이 잘 이루어진 것을 확인할 수 있다.

audio를 출력하여 직접 들어본 결과 역시 fade-out이 잘 이뤄짐을 확인할 수 있었다.
4.1. fade out 과 유사하게 진행하되, 연산위치와 가중치만 바꿔주면 된다.
연산위치는 음악의 앞부분,
가중치는 점진적으로 커쳐야하기 때문에, linspace(0.0,1.0,length)를 사용한다.





결과는 위와 같이 예쁘게 fade in이 된 것을 확인 할 수 있다.


새롭게 정의한 함수는 위의 두 가지이다.
하나는 waveform(소리의 파동) 출력함수이고, 하나는 specgram(소리의 스펙트럼) 출력함수이다.
파형에서는 시간축의 변화에 따른 진폭 축의 변화를 볼 수 있고, 스펙트럼에서는 주파수 축의 변화에 따른 진폭 축의 변화를 볼 수 있는 반면, 스펙트로그램에서는 시간축과 주파수 축의 변화에 따라 진폭의 차이를 인쇄 농도 / 표시 색상의 차이로 나타낸다. (http://ko.wordow.com/english/dictionary/spectrogram)
| [서버] 딥러닝-flask-firebase 연동하는 서버 (0) | 2023.06.25 |
|---|---|
| [서버] 딥러닝-mysql 연동하는 aws 서버 (0) | 2023.05.12 |