Epoch(50), 100개 레이어 고정

-> 결과 : 블루 스크린 뜸.. ㅎ

과하게 돌렸던걸로.. 어쩐지 컴퓨터가.. 시끄럽더라.. 하하

EarlyStopping 콜백을 사용

from tensorflow.keras.callbacks import EarlyStopping

early_stopping = EarlyStopping(
	monitor='val_loss',
    patience=10,
    restore_weights=True
)

history = model.fit(
    train_generator,
    validation_data=val_generator,
    epochs=50,  # 최대 에폭 수
    callbacks=[early_stopping]
)

 

에폭 수를 줄이고, EarlyStopping 콜백을 사용하여 모델이 더 이상 개선되지 않을 때 학습을 조기 종료할 수 있도록 하자

계속 테스트 하면서 시간도 체크하고, 결과물을 보고 에폭 수와 뉴런 수를 조절해야할 듯

epoch
에폭은 모델이 데이터를 몇 번 반복해서 학습할지

뉴런 수
현재는 Dense(512)인데 이처럼 층에 있는 뉴런 수가 많아지면 더 복잡한 패턴을 학습할 수 있다. 하지만 너무 많은 뉴런은 필요 이상으로 데이터를 학습하기에(과적합) 문제가 생길 수 있기에 조절 필요 그리고 학습 속도도 느려지고 계산 자원이 많이 필요함

 

epoch, 뉴런 수를 20, 216 으로 내려도 계속 블루스크린... 그래서 일단 epoch 수를 블루스크린 뜨기 전.. 10으로 뉴런 수를 216으로 설정하고 훈련 시킨 결과 ( 컴퓨터 소리도 커지고.. 또 블루스크린 뜰까봐 무서웠음.. 노트북에서는 실행 못 시킬 듯 다른 방법 찾아야 될 것 같음 ) 시간은 20분 정도 걸림

훈련시킨 사진 결과

other\n02085936_1325.jpg

sit\n02086079_186.jpg

sit\n02087046_4832.jpg

other\n02085620_7440.jpg

외부사진

dog-6240043_1280.jpg

외부사진 몇장 더 가지고 테스트를 해보아야겠지만.. 훈련시킨 사진으로는 이제 그래도 결과가 나오는 것처럼 보였으나 외부 사진을 보냈을 때 또 이상한 결과가 나옴.. 흑백에다가 하얘서 못알아보는건가..
.
.
.
아예 훈련시킨 이미지 외에는 제대로된 결과물을 가져오지 못하는 것 같다. 음... 방식을 추가해야할 듯

 

정확성을 위한 진행순서
1. OpenCV의 Haar-Cascade를 사용하여 강아지 얼굴을 감지한 후, 해당 영역을 중심으로 잘라내기

1. OpenCV 설치

가상환경 활성화된 상태에서 OpenCV를 설치

pip install opencv-python

 

 


 

아니 신나게 Haar-Cascade 분류기로 사용해서 코드 짜놨는데 사람 얼굴만 된다고... 왜 되는것처럼 말한거야 ㅠㅠㅠㅠ 씌ㅠㅠㅠㅠ 쨌든 Haar-Cascade분류기는 주로 얼굴 인식, 눈 검축 등에 사용되지만, 강아지 인식을 위한 사전 학습된 모델은 기본적으로 포함되어 있지 않는다고 함. 다른 방식을 도입해야 됨..

 

강사님과 상의한 결과

일단 사진을 줄여서 좋은 데이터로 여러 방향 여러 각도로 돌려 전처리 처리하는 것이 확률을 더 높일 수 있을 것

ResNet50, YOLO

 


 

MobileNet과 ResNet은 모두 이미지 분류 및 인식에 널리 사용되는 신경망 구조

기존 사용했던 거는 MobileNet

MobileNet -> 모바일, IoT 기기에서 이미지 분류, 객체 탐지 등 실시간 처리가 필요한 환경 / 경량화 덕분에 연산이 빠르고 메모리 사용량이 적음

ResNet (Residual Network)

  • 네트워크가 깊어질수록 발생하는 기울기 소실(Gradient Vanishing) 문제를 해결하기 위해 설계
  • 정확성이 중요한 상황에서 이미지 분류, 객체 탐지, 얼굴 인식 등에서 주로 사용.
  • MobileNet에 비해 연산이 느리고 메모리 사용량이 많음.

좀 더 자세히 찾아볼 걸 그랬나 속도와 경량화 보다 정확성이 중요하므로 RestNet을 사용!

기존 MobileNet에서 ResNet으로 변경 후 2차 테스트

sit\n02086646_3234.jpg

 

other\n02085620_3033.jpg

other\n02085620_5312.jpg

문제는 이제 다 확률은 높게 나오는데 앉은 모습이 아닌 모습도.... 앉기 행동으로 나온다.. 하하하하ㅏㅏ핳

이대로는 안돼............ 좀 더 세밀하게 조절해야해 사진을 좀 걸러야겠다

이거 그리고 other 사진에 앉아있는 강아지 사진 애매하게 들어있어서 안되는거같기도 사진 걸러야해

내부클래스

내부 클래스는 한 클래스 내부에 정의된 클래스, 이 클래스는 외부 클래스와 강한 연관성을 가지며, 논리적으로 그룹화된 기능을 제공할 수 있다.

  • 패키지 구조를 간소화
  • 외부 클래스의 멤버에 쉽게 접근
  • 특정 기능이 다른 클래스와 긴밀히 연결된 경우, 코드의 가독성과 유지보수성이 높아짐

 

1_000_000_000과 같은 언더스코어(_)를 사용한 숫자 표현은 큰 숫자를 더 읽기 쉽게 만듦

long 타입일 때 1_000_000_000 와 같이 사용하여도 정수 타입으로 사용가능


Spring Batch의 Job과 Step 구성

Spring Batch는 배치 작업을 Job과 Step으로 나누어 관리

  • Job : 전체 배치 작업을 정의하며 여러 Step으로 구성
  • Step : 각 Step은 하나의 단위 작업을 의미, Tasklet 또는 Item 처리기로 구성

Step의 구성 요소

  1. ItemReader: 데이터를 읽어오는 역할 (DB, 파일, API 등에서 데이터 읽기)
  2. ItemProcessor: 데이터를 변환하거나 가공
  3. ItemWriter: 처리된 데이터를 저장 (DB, 파일 등에 저장)

Chunk 기반 처리

  • chunk는 데이터를 여러 개의 작은 단위로 나누어 처리하는 방식 / 예를 들어, 1만 개의 데이터를 처리해야 한다면 한 번에 100개씩 (chunk size) 나누어 처리

chunk(청크) 동작 흐름
1. 리더 : 한 번에 100개 데이터를 읽음
2. 프로세서 : 100개 데이터를 변환 또는 가공
3. 라이터 : 처리된 100개 데이터를 DB에 저장

 

장점

  • 메모리 효율적 : 한 번에 모든 데이터를 메모리에 로딩하지 않는다.
  • 중간에 실패할 경우, 이전 처리된 청크까지는 저장되어 작업을 재개할 수 있다.

 

page size와 Chunk size

page size와 chunk size를 동일하게 설정하는 것이 좋다.

  • page size : 한 번에 읽어오는 데이터 수
  • chunk size : 한 번에 처리하는 데이터의 단위

page size와 chunk size가 다르면 메모리와 성능의 최적화가 어려워지기에 chunk size만큼 데이터를 처리하려고 할 때 추가적인 메모리 로드가 발생할 수 있기 때문

Foreign key 제약 조건과 문제

FK는 두 테이블 간의 참조 관계를 설정 (Order 테이블의 주문 항목(OrderItem)은 주문(Order)의 ID를 Foreign Key로 참조

 

Foreign Key 제약 조건
-> FK로 연결된 데이터가 있는 경우, 참조된 데이터가 삭제되지 않는다. (주문 항목이 존재할 때 주문을 삭제할 수 없다.)

 

제약 조건 제거의 필요성
정산 작업에서는 제약 조건을 제거하는 것이 좋다.

  • 대량 데이터 처리 시 FK가 있으면 성능 저하가 발생할 수 있다.
  • 정산 테이블은 클라이언트가 수정할 수 있어야 하므로 FK 제약이 불필요

format (..., 0) 금액은 천단위(1,000)로 표시 / 1,000,000 같은 형식

'Spring Batch' 카테고리의 다른 글

Spring Batch (10.16) - 환경세팅, Job, Step, tasklet  (0) 2024.10.16

대량의 사진 파일을 딥러닝 프로젝트에 사용하므로, GitHub에 직접 올리지 않고, 외부 저장소에 업로드한 후 코드로 연동

Google Drive 연동

  1. Google Drive에 사진 파일 업로드 (zip 압축파일로 만든 후 업로드)
  2. 업로드한 파일을 공유 가능 링크로 설정
  3. gdown 라이브러리 설치 및 사용
# gdown 설치
python -m pip install gdown
import gdown
import zipfile

def download_file(file_id, output):
    url = f'https://drive.google.com/uc?id={file_id}'
    print(f"Downloading {output}...")
    gdown.download(url, output, quiet=False)
    print(f"{output} downloaded.")

def extract_zip(file_name, extract_to):
    if os.path.exists(file_name):
        print(f"Extracting {file_name}...")
        with zipfile.ZipFile(file_name, 'r') as zip_ref:
            zip_ref.extractall(extract_to)
        print(f"{file_name} extracted to {extract_to}.")
    else:
        print(f"{file_name} not found.")

if __name__ == "__main__":
    #Google Drive 에서 가져온 파일 Id
    sit_file_id = '1QFqTjMe4Ti_WcY3Ez8q6laK1aQjJlNIE' # sit.zip 파일 ID
    other_file_id = '1-yr0u0e9xHFV6_tjWsi0yYlceyb8l3pa' # other.zip 파일 ID

# 데이터 폴더 생성 
os.makedirs('data', exist_ok=True)

# 파일 다운로드 
download_file(sit_file_id, 'dog_behavior_analysis/data/sit.zip')
download_file(other_file_id, 'dog_behavior_analysis/data/other.zip')

#압축 해제 경로 설정
os.makedirs('dog_behavior_analysis/data/sit', exist_ok=True)
os.makedirs('dog_behavior_analysis/data/other', exist_ok=True)

#압축해제
extract_zip('dog_behavior_analysis/data/sit.zip', 'dog_behavior_analysis/data')
extract_zip('dog_behavior_analysis/data/other.zip', 'dog_behavior_analysis/data')

# 데이터 경로 설정
sit_path = r'C:/Users/admin/IdeaProjects/TailsRoute_PJ/VScode/data'
other_path = r'C:/Users/admin/IdeaProjects/TailsRoute_PJ/VScode/data'
  1. README.md 파일에 사용자가 어떻게 데이터 다운로드 후 사용할지 설명글 적어두기

실행 순서

  1. sit 폴더와 other 폴더에 이미지 데이터 준비
  2. 이미지를 동일한 사이즈로 조절

ModuleNotFoundError: No module named 'sklearn'

Scikit-learn

Scikit-learn은 Python에서 머신러닝과 데이터 분석을 쉽게 수행할 수 있도록 제공되는 오픈소스 라이브러리

pip install scikit-learn

 

preprocess.py 작성, train_model.py 작성 후 모델 훈련 시키려고 하는 도중 위와 같은 에러 나옴 ..

위는 사이킷 런이라고하는 머신러닝 알고리즘을 구현한 파이썬 라이브러리! 설치가 안되어있었나봐

 


image = load_img(image_path, target_size=(224, 224))
image = img_to_array(image) / 255.0

 

이미지는 일반적으로 행렬로 표현, RGB 컬러 이미지는 3차원을 이루어져 있음
image 크기를 224 X 224 크기로 동일하게 적용시키고, img_to_array으로 이미지를 Numpy 배열로 변환하여 각 픽셀의 값을 직접 접근하고 사용할 수 있게 한다.

그리고 /255.0 (정규화) -> 픽셀 값은 0~255 사이의 정수 값, 딥러닝 모델에서 입력 데이터를 정규화하는 것은 매우 중요, 특히 이미지의 경우 픽셀 값을 0~1 사이의 실수 값으로 변환하는 것이 일반적

  • 그래서 이미지를 Numpy 배열로 변환한 뒤 / 255.0 을 해줌으로써 모든 픽셀 값을 255으로 나누어 각 픽셀을 0.0에서 1.0 사이의 값으로 변환해줌

딥러닝 모델은 배치 단위로 데이터를 입력받도록 설계되어 있다.

배치 단위란 한 번에 여러 개의 데이터를 처리하는 방식으로, 모델의 입력 데이터 형태는 보통 (배치 크기, 높이, 너비, 채널)이다.

 

단일 이미지를 입력하더라도, 모델이 요구하는 입력 형태로 만들기 위하여 배치 차원을 추가해야한다.

1차 test

import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import load_img, img_to_array


# 모델 경로 설정
model_path = r'C:\Users\admin\IdeaProjects\TailsRoute_PJ\VScode\dog_behavior_analysis\models\dog_behavior_model.keras'

# 모델 불러오기
model = load_model(model_path)
print("모델 정상 작동")

#테스트 이미지 로드 및 전처리
image_path = r'C:\Users\admin\IdeaProjects\TailsRoute_PJ\VScode\dog_behavior_analysis\data\sit\n02085782_754.jpg' # 이미지 경로
image = load_img(image_path, target_size=(224, 224)) # 이미지 크기 
image = img_to_array(image) / 255.0 # 정류화 (0-1 사이 값으로 변환)
image = np.expand_dims(image, axis=0) # 배치 차원 추가

# 예측 수행
prediction = model.predict(image)

# 결과 출력
if prediction[0][0] >= 0.5:
    print(f"예측 결과: 앉기 행동 (확률: {prediction[0][0]:.2f})")
else:
    print(f"예측 결과: 기타 행동 (확률: {prediction[0][0]:.2f})")

 

이미지 자체를 전처리하고 훈련시킨 다음 test한 결과 앉아 있는 모습을 물어보니 다른 기타 행동이라고.. 결과 나옴.. 심지어 확률이 무슨 0.3..?ㅋㅋㅋ

이래서 강사님이 축을 맞춰야된다고 하셨구나..

찾아보니 OpenCV 영상만 되는줄알았는데 이미지 전처리도 되는구나 OpenCV를 활용해서 특정 부분에 중심점을 기준으로 이미지 정렬시켜야함

환경세팅

@Bean
public Job helloWorldJob() {
    return jobBuilderFactory.get("helloWorldJob")
            .incrementer(new RunIdIncrementer()) // 매번 다른 ID로 실행 가능하게 설정
            .start(helloWorldStep1()) // 첫 번째 스텝 시작
            .build();
}

 

Job -> 하나 이상의 step으로 구성된 단위 작업
RunIdIncrementer -> 실행 시마다 새로운 JobInstance ID를 부여해 여러 번 동일한 작업을 실행할 수 있도록 / 같은 Job을 여러 번 실행할 때 충돌을 방지

@Bean
public Step helloWorldStep1() {
    return stepBuilderFactory.get("helloWorldStep1")
            .tasklet(helloWorldTasklet()) // Tasklet 설정
            .build();
}

 

Step -> Job의 하위 단위로, 배치 작업의 한 단계를 의미
Tasklet을 사용하여 간단한 작업을 수행

  • Tasklet은 Step 안에서 실행되는 작업의 실제 내용 / 간단한 작업이나 한 번만 수행되는 작업을 처리할 때 사용
@Bean
public Tasklet helloWorldTasklet() {
    return (stepContribution, chunkContext) -> {
        System.out.println("helloWorld!"); // "helloWorld!" 메시지 출력
        return RepeatStatus.FINISHED; // 작업 완료 표시
    };
}

 

tasklet -> 단순한 반복 가능한 작업 단위
RepeatStatus.FINISHED를 반환하여 작업이 한번만 실행되고 종료됨

Spring Batch는 하나의 큰 작업(Job)을 여러 단계(Step)로 나누어 처리, 각 Step 안에서는 특정 작업을 실행하는 코드가 Tasklet이나 Chunk로 구현


스프링 객체 생명주기

  1. 싱글톤(Singleton)
  • 스프링 부트 애플리케이션이 실행되는 동안 동일한 객체가 유지
  • 빈(Bean)이 한 번 생성되면 스프링 컨테이너가 종료될 때까지 같은 객체를 사용
  1. 세션(Session)
  • 브라우저에서 하나의 세션이 유지되는 동안 같은 객체를 사용
  • 세션이 종료되면 해당 객체도 소멸
  • @SessionScope
  1. 리퀘스트(Request)
  • 요청이 처리되는 동안 객체가 생성되고, 응답 후 소멸
  • 주로 컨트롤러나 서비스에 사용
  • @RequestScope
  1. 프로토타입(Prototype)
  • 스프링 컨테이너가 요청할 때마다 새로운 객체
  • 컨테이너는 객체를 생성한 후, 추가 관리 없이 바로 반환
  • @Scope("prototype")

mysqldump 및 데이터베이스 백업과 복원

mysqldump -u root SpringBatch_10 > SpringBatch_10.sql
  • mysqldump는 MySQL 데이터베이스의 백업을 생성하는 명령어
  • -u root 데이터베이스에 접근할 사용자를 지정
  • SpringBatch_10 백업할 데이터베이스 이름
  • > SpringBatch_10.sql 백업 결과를 SpringBatch_10.sql 파일로 저장
mysql -u root SpringBatch_10_backup < SpringBatch_10.sql
  • 백업된 데이터베이스를 복원
  • -u root MySQL 서버에 접근할 사용자
  • SpringBatch_10_backup 복원할 데이터베이스 이름
  • < SpringBatch_10.sql 백업 파일로부터 데이터를 가져와 복원

자동으로 덮어쓰기

동일한 데이터베이스 이름으로 복원할 경우, 기존 데이터가 덮어쓰기될 수 있다.


스프링 배치 명령 실행 흐름

  1. 명령 1번 실행
  • 모든 Step이 성공하면 작업이 완료, 실행 결과는 테이블에 기록
  1. 같은 명령이 2번 실행
  • 이전 실행 결과가 성공한 경우, 배치 시스템은 재실행을 건너뜀 (이미 같은 작업이 수행된 것을 알고, 중복 실행을 막는다.)


 

  • JPA와 Hibernate를 활용하면 객체를 데이터베이스와 매핑하여 자동으로 Insert 작업을 수행할 수 있다.
  • save() 메서드를 호출하기만 하면 복잡한 SQL 없이도 데이터베이스에 데이터를 삽입할 수 있다.
  • 트랜잭션, Service 계층을 통해 데이터 일관성을 유지할 수 있으며, Controller에서 API를 통해 요청을 처리한다.

'Spring Batch' 카테고리의 다른 글

Spring Batch (10.21) - 내부클래스, Chunk  (0) 2024.10.21

목표

사용자가 비디오를 업로드하면 자동으로 강아지의 행동을 분석, 적절한 훈련 방법을 제안

기능 시나리오

1. 자바 페이지를 보여준다. -> 동영상 업로드

2. 업로드 한 동영상을 Python으로 분석

3. 분석 결과를 다시 flask 활용해서 자바로

4. 자바에서는 결과 값을 보여줌

진행순서

강아지의 특정 행동에 대한 테스트 영상 ( 앉기) 필요

일단 시스템의 주요 기능은 (비디오 업로드, 행동 분석, 추천 제공 )
원래의 기능 목적은 사용자가 이상행동을 보이는 반려견 영상을 보낼 시 이를 분석하고 해결할 수 있는 영상을 추천하는 목적이지만, 현재로써 제일 처음으로는 사용자가 반려견의 행동(앉아, 기다려 등등 일단 나는 앉아를 사용할 예정)을 보낼 시 이를 분석하여 어떤 행동인지 알아내고 사용자한테 제시 할 수 있는 것까지 초반을 잡고, 성공 한다면?

반대로 이상행동인 영상을 업데이트하고 해당 영상분석하여 행동 교정 할 수 있도록 사용자에게 텍스트로 전달할 것인지, 영상으로 전달할 것인지 선택하여 진행하면 될 것 같다.

 

AI는 어떻게 활용하 것인가ㅡ

 

이제 문제는 강아지 행동에 대한 데이터셋을 어떻게 수집하지
-> 수집했다면 tensorflow를 사용하여 행동을 인식할 수 있는 모델 훈련, (사전 학습된 모델이 있을까?)

그래서 작업 순서는

 

데이터셋.. 음.. 유튜브와 Stanford Dogs Dataset라는 다양한 강아지 종의 이미지를 포함하는 이미지 데이터셋이여서 유튜브에 한가지 행동만 보여주는 영상이 한정적이기에 아니면 내가 영상 길이까지 조절할 수 있나.. 음,, 어쨌든 Stanford Dogs Dataset 이미지 데이터셋이다보니 원래는 행동보다는 외형을 인식하는 데 주로 사용된다고 하는데, 데이터를 전처리하고 행동 분석과 결합해서 사용가능하도록...

 

그리고 영상찍은 데이터도 같이 넣어서 최대한 다른 각도에서!

아 어짜피 전처리하면 유튜브에서 긁어와도 될듯? (근데 저작권 뭐.. 그런거 상관없나)
OpenCV를 사용해서 프레임 단위로 변환 ( 이미지를 크롭하거나 크기를 조정하여 모델 훈련에 적합한 형식으로 준비 )

일단 그러면

결론

  1. Stanford Dogs Dataset이나 다른 개 행동 관련 이미지 데이터셋을 사용하여 "앉기" 행동을 감지하는 모델을 훈련
  2. ResNet, MobileNet 등의 사전 학습된 이미지 인식 모델에 추가적인 분류기 학습
  3. 강아지 행동을 이미지에서 잘 인식하는지 테스트하고, 성능을 평가
  4. 영상 데이터 준비:
    사용자가 업로드한 영상 데이터를 OpenCV를 사용하여 프레임 단위로 분해
    각 프레임을 앞서 훈련된 이미지 모델에 입력하여 행동 인식을 수행

영상 분석 기능 통합:
각 프레임에서 인식된 결과를 시간 순으로 통합하여 영상 내에서 특정 행동이 언제 발생했는지를 판단
행동 인식 결과를 영상 전체에서 시각적으로 표시하거나 시간대별로 나눠 사용자에게 제공

이후에는 "앉기"와 같은 정상 행동 인식에서 시작하여, 향후에는 이상 행동을 감지하고 적절한 교정 방법을 추천하는 방식으로 발전

개 행동 분석 데이터 세트
https://www.kaggle.com/datasets/arashnic/animal-behavior-analysis/data

트러블슈팅 🫨

js 수정시키기 위해 webpack 실행시켰는데, 위와 같은 오류가 발생했는데, webpack이 node_modules 폴더에서 설치되지 않았거나 손상되었기 때문에 발생하는 문제라고 함

기존 node_modules 폴더가 손상되었을 가능성이 있을 수 있기에 이를 삭제하고 다시 설치

Remove-Item -Recurse -Force .\node_modules\
npm install

해결✅

  1. 400 Bad Request

 

잘되던 로그인이 코드를 새로 바꾸다보니 안되더라... 위와 같은 오류가 나왔고, 찾아보니 클라이언트 데이터 요청 형식이 맞지 않아 발생한 문제..? 그래서 클라이언트에서 URL 인코딩된 데이터를 fetch 요청으로 전송 Content-Type을 application/x-www-form-urlencoded로 설정 그리고 나서도 오류가 나서 찾아보니 메서드에서도 JSON 형식으로 응답으로 반환하도록 수정해야한다. 그래서 return 할때, Map<String, Object> response으로 response를 반환

해결✅

-> 코드.. 리액트로만 활용하다가 원래 사용했던 코드가 꼬이면서 발생한 문제인 것 같다.. 하하하 생고생하는 느낌

thymeleaf, react 충돌..

리액트 사용은 따로 해서 충돌 안나게 하면 상관없다고 했는데.. 생각해보니 공통으로 사용하고있는 head가 타임리프로... 하하하ㅏ하 거기까지 생각을 못했네 하하핳

이제 선택은? 리액트를 다 없애버리고.. 원래 방식으로... 하지만.. 난.. 포기못하지.... 하하핳 리액트 그래도 한번쯤 사용해보고 싶었는ㄷ데..

리액트사용하는 곳은 react-helmet 라이브러리, 라우터를 활용해서 signup도 되도록.. 코드를.. 뜯어 고쳐야겠네

Thymeleaf를 더 이상 사용하지 않고, React Router를 사용하여 로그인페이지를 React 컴포넌트로 전환

 

아닌가.. 그냥 가야하나..
괜한 짓을 하는 것같기도.. 하고... 그냥..... 빨리 다른걸 하는게 나을 수 도.....

 


 

일단... 해보는거지.. 공부도 하고 좋지 뭐..

  1. head.js 부터 만들고 login과 연결 ⭕
  2. 라우터
  3. signUp

+ Recent posts