EunSeong Lee Portfolio
Project
AI_mini_prj
Avoid Bullets
Digital Clock
Subsubcategory 1
Subsubcategory 2
post-03
Study
AI Algorithm Structure
LAB
ASIC FrontEnd
post-01
post-02
Arm Architecture
post-01
CMOS VLSI Design
LAB
THEORY
CPU Design
CODE
LAB
THEORY
FPGA
LAB
THEORY
comment system
Home
markdown
portfolio
Contact
Copyright © 2024 |
Yankos
Home
>
Study
> AI Algorithm Structure
Please wait ...
AI Algorithm Structure
Day6: Convolutional Neural Network
이미지 분류 이미지 분류는 컴퓨터가 사람처럼 시각적으로 사물을 인식하고 분류하는 Computer Vision 분야의 핵심 작업에 해당한다. CNN(합성곱 신경망)은 기존 신경망보다 정교한 분석이 가능하며, 깊은 층을 통해 이미지의 특징을 고도화된 필터로 추출한다. 분류 유형 이진 분류(Binary): 두 개의 클래스(예: 정상/비정상) 중 하나로 분류한다. 다중 클래스(Multiclass): 세 개 이상의 클래스 중 하나로 분류한다(예: 고양이/개/토끼). 다중 라벨(Multilabel): 한 이미지가 여러 라벨을 동시에 가질 수 있다. 계층적 분류(Hierarchical): 클래스가 계층 구조로 조직되어 상위-하위 개념을 구분한다. 핵심 단계 데이터 수집: 충분한 양의 이미지와 라벨을 확보한다. 특징 추출: 이미지에서 의미 있는 특징(엣지, 색상, 질감 등)을 추출한다. 분류: 추출된 특징을 바탕으로 이미지를 올바른 클래스에 할당한다. 전이학습(Transfer Learning): 사전학습된 모델의 가중치를 재사용해 적은 데이터로도 높은 성능을 낼 수 있다. CNN 구성요소 구성요소 역할 및 설명 입력층(Input Layer) 원본 이미지의 픽셀 데이터를 입력받는다. 이미지의 크기(예: 224x224x3)가 입력 크기를 결정한다. 합성곱층(Convolutional Layer) 여러 개의 필터(커널)를 이미지에 슬라이딩하며 지역적 특징(엣지, 패턴 등)을 추출한다. 각 필터는 특성 맵을 만든다. 활성화 함수(Activation Function) 주로 ReLU를 사용한다. 음수 값을 0으로 바꿔주고, 비선형성을 부여해 복잡한 패턴 학습이 가능하게 한다. 풀링층(Pooling Layer) 특성 맵의 공간적 크기를 줄여 계산량을 감소시키고 과적합을 방지한다. Max pooling(최댓값 추출)이 대표적이다. 완전 연결층(Fully Connected Layer) 추출된 특징을 1차원 벡터로 변환(flatten)한 후, 모든 뉴런이 서로 연결되어 최종 분류를 진행한다. 출력층(Output Layer) 클래스별 확률값을 출력한다. 다중 클래스 분류에서는 Softmax 함수로 확률값을 정규화한다. 드롭아웃(Dropout, 선택적) 일부 뉴런을 무작위로 비활성화해 과적합을 방지하는 정규화 기법이다. 합성곱(Convolution) 연산 입력 이미지에 작은 필터(예: 3x3)를 슬라이딩하며 곱셈·합산을 반복해 특징 맵을 생성한다. 필터의 개수만큼 여러 특징 맵이 만들어지며, 각 필터는 엣지, 질감 등 특정 패턴에 반응한다. 필터의 이동 간격은 stride, 경계 처리를 위한 패딩(padding) 등도 주요 파라미터에 해당한다. 풀링(Pooling) 연산 MaxPooling(최댓값), AveragePooling(평균값) 등이 있으며, 공간 정보를 요약해 연산량을 줄이고, 위치 변화에 강인한 특징을 학습한다. GlobalAveragePooling은 전체 맵의 평균값만 남겨 FC층 전에 차원을 크게 줄일 수 있다. Flatten & FC Layer 합성곱·풀링을 반복한 후, 결과를 1차원 벡터로 변환(flatten)하여 완전 연결층에 입력한다. FC층은 전통적인 신경망처럼 모든 뉴런이 서로 연결되어 최종 분류를 담당한다. 이미지 학습과정 데이터 준비 및 전처리 이미지 수집 및 라벨링: 충분한 양의 이미지를 수집하고, 각 이미지에 라벨(정답)을 부여한다. 데이터 증강(Data Augmentation): 회전, 뒤집기, 밝기 조정, 확대/축소 등으로 데이터 다양성을 확보하고 과적합을 방지한다. 정규화 및 리사이즈: 픽셀 값을 0~1 범위로 정규화하고, 모델 입력 크기에 맞게 리사이즈한다. ImageDataGenerator Keras 등에서 제공하는 ImageDataGenerator를 활용하면, 실시간으로 데이터 증강 및 전처리를 자동화할 수 있다. flow_from_directory: 디렉토리 구조별로 이미지를 불러오고 자동 라벨링한다. flow_from_dataframe: DataFrame에서 경로와 라벨을 읽어 배치 단위로 불러온다. 특징 추출 및 모델 학습 합성곱/풀링/활성화: CNN의 여러 층을 거치며 이미지로부터 점점 더 추상적인 특징을 자동으로 추출한다. 완전 연결층: 추출된 특징을 바탕으로 최종적으로 클래스별 확률을 산출한다. 평가 및 검증 검증 데이터셋 활용: 학습에 사용하지 않은 별도의 데이터로 모델 성능을 평가한다. 성능 개선: 필요시 하이퍼파라미터를 조정하거나 데이터 증강, 레이어 추가 등으로 성능을 개선한다. 테스트 및 배포 실제 환경에서 미지의 이미지를 분류하여 모델의 실전 성능을 검증한다. CNN 아키텍처 아키텍처 주요 특징 및 구조 LeNet-5 1998년에 제안되었으며, 2개의 합성곱+풀링층과 3개의 완전 연결층으로 구성된다. 소형 이미지(28x28, MNIST 등) 분류에 적합하다. AlexNet 2012년 ILSVRC에서 우승하였으며, 5개의 합성곱층+3개의 완전 연결층, ReLU 활성화 함수 도입, 대규모 이미지(224x224) 분류에 사용된다. VGG-16 13개의 합성곱층+3개의 완전 연결층, 모든 합성곱 커널 크기를 3x3으로 통일하여 깊은 구조(16층)로 일관된 구조를 가진다. ResNet 2015년 ILSVRC에서 우승하였으며, 50~152개 층의 초심층 구조와 잔차 연결(residual connection)로 학습 효율을 극대화한다. Inception 다양한 크기의 필터를 병렬로 적용(Inception 모듈), 1x1 합성곱으로 연산량을 감소시키고 GlobalAveragePooling을 사용한다. MobileNet 모바일/임베디드 환경에 최적화된 경량화 구조로 실시간 분류가 가능하다. 전이학습(Transfer Learning) 활용 최신 실무에서는 사전학습된 CNN 모델을 가져와 출력층만 교체하거나 일부 층만 미세조정(Fine-tuning)하여 적은 데이터로도 좋은 성능을 얻는다. 공통 구조 입력 → [합성곱 → 활성화 → 풀링] × N → (필요시 드롭아웃) → 완전 연결층 → 출력(Softmax) 순으로 진행한다. 특징 특징 추출부(Feature Extractor): 여러 합성곱/풀링층이 반복되어 이미지의 저수준(엣지)부터 고수준(객체)까지 특징을 추출한다. 분류부(Classifier): 완전 연결층에서 추출된 특징을 바탕으로 클래스별 확률을 산출한다. 정리 이미지 분류는 이미지를 클래스별로 자동 분류하는 작업이며, CNN은 이를 위한 대표적 딥러닝 모델이다. CNN은 입력층, 합성곱층, 활성화함수, 풀링층, 완전 연결층, 출력층 등으로 구성되며, 각 층이 계층적으로 쌓여 특징을 추출하고 분류를 수행한다. 학습과정은 데이터 준비, 전처리, 모델 학습, 평가, 테스트 순으로 진행한다. 대표적인 CNN 아키텍처로는 LeNet, AlexNet, VGG, ResNet, Inception, MobileNet 등이 있으며, 각각의 구조와 특징이 다르다. 실습 학습 목표 CNN의 기본 개념과 이미지 분류에서의 역할을 이해한다. CNN의 주요 구성요소(입력층, 합성곱층, 활성화 함수, 풀링층, 완전 연결층 등)를 설명할 수 있다. 이미지 학습과정(데이터 준비, 전처리, 모델 학습, 평가, 테스트)을 이해한다. 학습곡선을 해석하고 오버피팅 문제를 인식하며, 개선 방법을 습득한다. 딥러닝 모델의 하이퍼파라미터 튜닝과 전이학습 활용법을 이해한다. CNN Layer 구현 CNN 모델 디자인 from tensorflow.keras import models, layers model = models.Sequential() # (32, 32, 3) => (30, 30, 32) model.add(layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(32, 32, 3))) # (30, 30, 32) => (15, 15, 32) model.add(layers.MaxPool2D(pool_size=(2, 2))) # (15, 15, 32) => (13, 13, 64) model.add(layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu')) # (13, 13, 64) => (6, 6, 64) model.add(layers.MaxPool2D(pool_size=(2, 2))) # (6, 6, 64) => (4, 4, 64) model.add(layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu')) # 3D를 1D로 변환 model.add(layers.Flatten()) # Classification : Fully Connected Layer 추가 model.add(layers.Dense(units=64, activation='relu')) model.add(layers.Dense(units=10, activation='softmax')) # 모델의 학습 정보 설정 model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) # 모델 학습 history = model.fit(x=train_x, y=train_y, epochs=20, batch_size=256, verbose=2, validation_split=0.2) Accuracy Loss 학습곡선 해석 및 오버피팅 개선 방안 1. 그래프 해석 Training Accuracy/Loss 학습 정확도는 꾸준히 상승하여 0.9(90%)에 근접한다. 학습 손실(loss)은 꾸준히 감소해 0.4 이하로 떨어진다. Validation Accuracy/Loss 검증 정확도는 0.8(80%) 부근에서 더 이상 오르지 않고, 에포크가 진행될수록 상승이 멈추거나 약간 하락/변동한다. 검증 손실은 0.7~0.8 선에서 변동하며, 오히려 에포크가 늘수록 올라가기도 한다. 2. 원인 분석 오버피팅(overfitting) 현상. 오버피팅이란? 모델이 학습 데이터에는 매우 잘 맞지만, 새로운 데이터(검증/테스트)에는 일반화가 잘 안 되는 상태. 구체적 신호 학습 손실은 계속 감소(=학습 데이터에 점점 더 잘 맞춤) 검증 손실은 어느 순간부터 더 이상 감소하지 않고, 오히려 증가하거나 불안정하게 변동 학습 정확도와 검증 정확도의 차이가 점점 커짐 3. 왜 이런 현상이 생기나? 모델이 너무 복잡하거나 파라미터가 많을 때 학습 데이터에 비해 검증 데이터의 분포가 다를 때 데이터가 충분히 다양하지 않거나, 데이터 증강이 부족할 때 드롭아웃, 정규화 등 일반화 기법이 부족할 때 에포크 수가 너무 많아 불필요하게 오래 학습할 때 4. 이런 경우 어떻게 해야 하나? Early Stopping(조기 종료) 사용: 검증 손실이 더 이상 감소하지 않으면 학습을 멈춘다. 드롭아웃(Dropout)·정규화(BatchNorm) 추가: 모델이 일부 뉴런에 의존하지 않도록 하고, 학습을 안정화한다. 데이터 증강(Data Augmentation): 학습 데이터를 회전, 이동, 노이즈 추가 등으로 다양하게 만든다. 모델 단순화: 층 수나 파라미터 수를 줄여 복잡도를 낮춘다. 학습률(learning rate) 조정: 너무 높으면 불안정, 너무 낮으면 과적합으로 이어질 수 있다. 더 많은 데이터 확보: 가능하다면 데이터셋을 키운다. 5. 참고: 정상적인 학습곡선은? 학습·검증 손실이 모두 점진적으로 감소 학습·검증 정확도가 모두 점진적으로 증가 두 곡선 간의 차이가 크지 않음 (차이가 크면 오버피팅, 둘 다 낮으면 언더피팅) 결론 현재 학습곡선은 모델이 학습 데이터에는 과하게 맞추고, 새로운 데이터에는 일반화하지 못하는 전형적인 오버피팅 상태다. CNN 모델 개선 드롭아웃(Dropout)·정규화(BatchNorm) 추가: 학습률(learning rate) 조정: from tensorflow.keras import models, layers model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) model.add(BatchNormalization()) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(BatchNormalization()) model.add(layers.MaxPool2D((2, 2))) model.add(Dropout(0.5)) model.add(layers.Conv2D(128, (3, 3), activation='relu')) model.add(BatchNormalization()) model.add(layers.MaxPool2D((2, 2))) model.add(Dropout(0.5)) model.add(layers.Flatten()) model.add(layers.Dense(256, activation='relu')) model.add(Dropout(0.5)) model.add(layers.Dense(10, activation='softmax')) model.compile(optimizer=Adam(learning_rate=0.0002), loss='categorical_crossentropy', metrics=['accuracy']) history = model.fit(x=train_x, y=train_y, epochs=50, batch_size=128, validation_split=0.2, verbose=2) Accuracy Loss 결론 이번 학습을 통해 합성곱 신경망(CNN)의 구조와 원리를 이해하고, 실제 이미지 분류 문제에 적용해봄으로써 딥러닝 기반 컴퓨터 비전의 핵심 개념을 익혔다. CNN의 다양한 구성요소와 대표 아키텍처의 특징, 데이터 전처리와 정규화, 오버피팅 방지 기법 등 실전적인 내용을 학습함으로써, 이미지 분류 모델의 성능을 효과적으로 향상시키는 방법을 습득할 수 있었다. 향후에는 전이학습, 데이터 증강, 하이퍼파라미터 튜닝 등 고급 기법을 적극적으로 활용하여, 더 높은 성능과 실전 적용 능력을 갖춘 딥러닝 모델을 설계·활용할 수 있을 것이다.
Study
· 2025-06-30
Day5: Neural Network Model
Activate function Learning Analysis Optimization Techniques LAB Mnist 실습 1. 차이점 항목 신경망 구조 신경망❌구조 모델 구조 4개 Dense 계층(512→256→128→10), Dropout 3회 1개 Dense 계층(10) 활성화 함수 relu(은닉층), softmax(출력층) softmax(출력층) Dropout 사용 있음(0.3 비율, 3회) 없음 Optimizer Adam(learning_rate=0.0003) SGD(기본값) Epoch 수 35 30 Batch Size 128 64 모델 복잡도 높음 매우 단순(로지스틱 회귀와 유사) 2. 모델 구조 및 복잡도 신경망❌구조: 은닉층 없이 입력(784차원)에서 바로 10개 유닛의 softmax 출력층으로 연결된 매우 단순한 구조. 이는 다중 클래스 로지스틱 회귀와 동일. 신경망 구조: 3개의 은닉층(512, 256, 128 유닛)과 Dropout(0.3) 레이어를 포함해, 심층 신경망 구조. 출력층은 10개 유닛의 softmax. 신경망❌구조 md = Sequential() md.add(Dense(10, activation = 'softmax', input_shape = (28*28,))) 신경망 구조 md = Sequential() md.add(Dense(512, activation='relu', input_shape=(28*28,))) md.add(Dropout(0.3)) md.add(Dense(256, activation='relu')) md.add(Dropout(0.3)) md.add(Dense(128, activation='relu')) md.add(Dropout(0.3)) md.add(Dense(10, activation='softmax')) 3. 정규화(Dropout) 적용 유무 op_mnist.py는 과적합 방지를 위해 Dropout 레이어를 3번 사용. mnist.py는 Dropout 레이어 ❌ 4. Optimizer 및 하이퍼파라미터 설정 신경망❌구조 md.compile(loss='sparse_categorical_crossentropy', optimizer = 'sgd', metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 30, batch_size = 64, validation_split = 0.2) 신경망 구조 md.compile(loss='sparse_categorical_crossentropy', optimizer=Adam(learning_rate=0.0003), metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 35, batch_size = 128, validation_split = 0.2) 5. 결과 비교 신경망❌ 구조 신경망 구조 신경망❌ 구조 신경망 구조 신경망❌ 구조 신경망 구조 6. 결론 - 신경망❌구조는 단일층 신경망(로지스틱 회귀) 구조로, 구현이 간단하고 빠르지만, 복잡한 데이터 표현력은 떨어진다. - 신경망 구조는 심층 신경망(MLP) 구조에 Dropout과 Adam 옵티마이저를 적용해, 복잡한 패턴 학습과 과적합 방지에 중점을 둔 코드. - 두 코드의 차이는 모델 구조(심층 vs. 단층), 정규화 적용, 옵티마이저 종류, 학습 파라미터 등에서 뚜렷하게 나타난다. Cifar-10 실습 1. 차이점 항목 신경망 구조 신경망❌구조 모델 구조 4개 Dense 계층(512→256→128→10), Dropout 3회 1개 Dense 계층(10) 활성화 함수 relu(은닉층), softmax(출력층) softmax(출력층) Dropout 사용 있음(0.3 비율, 3회) 없음 Optimizer Adam(learning_rate=0.0003) SGD(기본값) Epoch 수 35 30 Batch Size 128 64 모델 복잡도 높음 매우 단순(로지스틱 회귀와 유사) 2. 모델 구조 및 복잡도 신경망❌구조: 은닉층 없이 입력(784차원)에서 바로 10개 유닛의 softmax 출력층으로 연결된 매우 단순한 구조. 이는 다중 클래스 로지스틱 회귀와 동일. 신경망 구조: 3개의 은닉층(512, 256, 128 유닛)과 Dropout(0.3) 레이어를 포함해, 심층 신경망 구조. 출력층은 10개 유닛의 softmax. 신경망❌구조 md = Sequential() md.add(Dense(10, activation = 'softmax', input_shape = (32*32*3,))) 신경망 구조 md = Sequential() md.add(Dense(512, activation='relu', input_shape=(3072,))) md.add(Dropout(0.3)) md.add(Dense(256, activation='relu')) md.add(Dropout(0.3)) md.add(Dense(128, activation='relu')) md.add(Dropout(0.3)) md.add(Dense(10, activation='softmax')) 3. 정규화(Dropout) 적용 유무 신경망 구조(op_cifar_10.py): 과적합 방지를 위해 Dropout 레이어를 3번 사용. 신경망❌구조(cifar_10.py): Dropout 레이어가 없다. 4. Optimizer 및 하이퍼파라미터 설정 신경망❌구조 md.compile(loss='sparse_categorical_crossentropy', optimizer = 'sgd', metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 30, batch_size = 64, validation_split = 0.2) 신경망 구조 md.compile(loss='sparse_categorical_crossentropy', optimizer=Adam(learning_rate=0.0003), metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 35, batch_size = 128, validation_split = 0.2) 5. 결과 비교 신경망❌ 구조 신경망 구조 신경망❌ 구조 신경망 구조 신경망❌ 구조 신경망 구조 6. 결론 신경망❌구조는 단일층 신경망(로지스틱 회귀) 구조로, 구현이 간단하고 빠르지만, 복잡한 데이터 표현력은 떨어진다. 신경망 구조는 심층 신경망(MLP) 구조에 Dropout과 Adam 옵티마이저를 적용해, 복잡한 패턴 학습과 과적합 방지. 두 코드의 차이는 모델 구조(심층 vs. 단층), 정규화 적용, 옵티마이저 종류, 학습 파라미터 등.
Study
· 2025-06-27
Day5: Linear Model
(Mnist, Cifar_10) Dataset 1. 데이터셋 및 코드 개요 ❓ Mnist 데이터셋이란? 손으로 쓴 숫자(0~9)를 인식하는 머신러닝 및 딥러닝 모델의 성능 평가를 위해 널리 사용되는 대표적인 이미지 데이터셋이다. 총 70,000개의 흑백(그레이스케일) 이미지로 이루어져 있으며, 60,000개는 학습용, 10,000개는 테스트용이다. 각 이미지는 28x28 픽셀 크기의 정사각형 형태이다. ❓ Cifar_10 데이터셋이란? 컴퓨터 비전 분야에서 이미지 분류 모델의 성능을 평가하기 위해 널리 사용되는 컬러 이미지 데이터셋이다. 총 60,000개의 컬러(RGB, 3채널) 이미지로 이루어져 있으며, 50,000개는 학습용, 10,000개는 테스트용이다. 각 이미지는 32x32 픽셀 크기이다. 2. 데이터 전처리 및 모델 구조 Mnist 데이터셋 데이터: (60000, 28, 28) 크기의 흑백 이미지, 라벨(0~9) 전처리: 이미지를 1차원(784)으로 변환 후 0~1 정규화 모델: 입력: Dense(3072) 출력층: Dense(10, softmax) (은닉층 없음) 손실함수: sparse_categorical_crossentropy 최적화: SGD 평가: 정확도(acc) # Mnist 데이터 전처리 train_x1 = train_x.reshape(60000, -1) # 1차원 배열 test_x1 = test_x.reshape(10000, -1) # 1차원 배열 train_x2 = train_x1/255 test_x2 = test_x1/255 print(train_x2.shape) # (60000, 784) print(test_x2.shape) # (10000, 784) md = Sequential() md.add(Dense(10, activation = 'softmax', input_shape = (28*28,))) md.summary() md.compile(loss='sparse_categorical_crossentropy', optimizer = 'sgd', metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 30, batch_size = 64, validation_split = 0.2) Cifar_10 데이터셋 데이터: (50000, 32, 32, 3) 크기의 컬러 이미지, 라벨(0~9) 전처리: 이미지를 1차원(3072)으로 변환 후 0~1 정규화 모델: 입력: Dense(3072) 출력층: Dense(10, softmax) (은닉층 없음) 손실함수: sparse_categorical_crossentropy 최적화: SGD 평가: 정확도(acc) # Cifar_10 데이터 전처리 train_x1 = train_x.reshape(50000, -1) # 1차원 배열 test_x1 = test_x.reshape(10000, -1) # 1차원 배열 train_x2 = train_x1/255 test_x2 = test_x1/255 print(train_x2.shape) #(50000, 3072) print(test_x2.shape) #(10000, 3072) md = Sequential() md.add(Dense(10, activation = 'softmax', input_shape = (32*32*3,))) md.summary() md.compile(loss='sparse_categorical_crossentropy', optimizer = 'sgd', metrics=['acc']) hist = md.fit(train_x2, train_y, epochs = 30, batch_size = 128, validation_split = 0.2) 3. 코드 실행 및 결과 시각화 Mnist 데이터셋 Cifar_10 데이터셋 4. 두 코드의 주요 차이점 항목 MNIST 코드 CIFAR-10 코드 데이터 타입 흑백(1채널), 28x28 컬러(3채널), 32x32 입력 차원 784 3072 모델 구조 은닉층 ❌ 은닉층 ❌ 난이도 상대적으로 쉬움 상대적으로 어려움 분류 대상 손글씨 숫자(0~9) 10가지 사물 성능 기대치 높은 정확도 달성 용이 단순 모델로는 낮은 정확도 데이터 복잡성: CIFAR-10은 색상, 배경, 형태가 다양해 단순 신경망으로는 분류가 어렵고, MNIST는 단순한 흑백 숫자 이미지라 기본 신경망도 높은 성능을 보임. 5. CIFAR-10 정확도 향상을 위한 하이퍼파라미터 조정 방법 1. 은닉층 추가 및 크기 조정: Dense 레이어(은닉층)를 추가하고, 노드 수를 늘리면 더 복잡한 패턴을 학습 은닉층이 없는 구조에 Dense(100, activation=’softmax’)로 하면 100개의 클래스에 대한 확률을 내놓기 때문에, 10개 클래스 분류 문제에서는 올바른 결과 ❌ 2. 활성화 함수 변경: 은닉층에 relu 등 비선형 활성화 함수를 적용해 모델 표현력을 높일 수 있다. 3. 배치 사이즈(batch size) 변경: 작은 배치는 더 빠른 업데이트, 큰 배치는 더 안정적인 학습을 유도 4. 에포크 수 조정: 더 오래 학습시키면 성능이 오를 수 있으나, 과적합에 주의 과적합은 모델이 학습 데이터의 노이즈나 세부적인 패턴까지 지나치게 학습하여, 새로운 데이터(테스트 데이터)에 대한 일반화 성능이 떨어지는 현상. 과적합된 모델은 학습 데이터에서는 높은 정확도를 보이지만, 테스트 데이터에서는 성능이 급격히 떨어진다. ❗과적합 방지법 조기 종료(Early Stopping): 검증 데이터의 성능이 더 이상 개선되지 않으면 학습 중단. 정규화(Regularization): L1, L2 정규화, 드롭아웃(Dropout) 등을 사용해 모델 복잡도 제어. 데이터 증강(Data Augmentation): 학습 데이터를 인위적으로 늘려 모델이 더 일반화되도록 한다. 적절한 에포크 수 설정: 검증 성능이 최고일 때 학습을 멈추는 것이 이상적이다. 6. 결론 정확도가 너무 낮은 것은 모델 구조의 한계 때문이다. 하이퍼파라미터 조정만으로는 근본적인 해결이 어렵다. 은닉층을 추가하거나 CNN을 사용하는 것이 좋을 것 같다.
Study
· 2025-06-27
Day4: Deep Learning
Compare Perceptron, Multi Layer perceptron XOR Gate 1. 네트워크 구조의 차이 Perceptron - Single layer : 입력층과 출력층만 존재하며, 입력값에 가중치와 바이어스를 더한 뒤 바로 출력 self.weights = np.zeros(input_size) self.bias = 0 - 활성화 함수: 계단함수와 같은 단순한 함수를 사용한다. Multi Layer Perceptron - Multi layer : 입력층, 은닉층, 출력층으로 구성된다. self.w1 = np.random.randn(input_size, hidden_size) self.b1 = np.zeros(hidden_size) self.w2 = np.random.randn(hidden_size, output_size) self.b2 = np.zeros(output_size) - 활성화 함수: sigmoid, tanh 등 연속적이고 미분 가능한 함수 사용. 각 층마다 적용한다. 2. 순전파 연산의 차이 Perceptron - 입력층 -> 출력층 linear_output = np.dot(x, self.weights) + self.bias return self.activation(linear_output) Multi Layer Perceptron - 입력층 -> 은닉층 -> 출력층 self.z1 = np.dot(x, self.w1) + self.b1 self.a1 = sigmoid(self.z1) self.z2 = np.dot(self.a1, self.w2) + self.b2 self.a2 = sigmoid(self.z2) return self.a2 3. 가중치 업데이트 방식의 차이 Perceptron - 단순 업데이트 update = self.lr * (target - prediction) self.weights += update * x1 self.bias += update Multi Layer Perceptron - 역전파(Backpropagation) 사용 출력층 오차를 은닉층까지 전파하여 모든 가중치/바이어스를 미분값(gradient)으로 업데이트한다 # 출력층 오차 error_output = self.a2 - y delta2 = error_output * sigmoid_diff(self.z2) # 은닉층 오차 error_hidden = np.dot(self.w2, delta2) delta1 = error_hidden * sigmoid_diff(self.z1) # 가중치 업데이트 self.w2 -= self.lr * np.outer(self.a1, delta2) self.b2 -= self.lr * delta2 self.w1 -= self.lr * np.outer(x, delta1) self.b1 -= self.lr * delta1 4. 문제 해결 능력의 차이 Perceptron - 퍼셉트론: XOR처럼 선형적으로 구분 불가능한 문제는 절대 풀 수 없음. 단일 직선(혹은 평면)만으로 데이터를 나눈다. Multi Layer Perceptron - MLP: 은닉층의 비선형 변환 덕분에 XOR 등 복잡한 패턴도 학습 가능. 실제로 MLP 코드는 XOR 문제를 성공적으로 해결할 수 있음 5. 코드 예시 Perceptron 출력층 오차만 사용 class Perceptron: def __init__(self, input_size, ...): self.weights = np.zeros(input_size) self.bias = 0 def predict(self, x): return self.activation(np.dot(x, self.weights) + self.bias) def train(self, X, y): Multi Layer Perceptron 여러 층 순전파 역전파로 모든 층 가중치 업데이트 class MLP: def __init__(self, input_size, hidden_size, output_size, ...): self.w1 = np.random.randn(input_size, hidden_size) self.b1 = np.zeros(hidden_size) self.w2 = np.random.randn(hidden_size, output_size) self.b2 = np.zeros(output_size) def forward(self, x): def backward(self, x, y): 6. 요약 구분 퍼셉트론 MLP 층 구조 입력-출력(단일층) 입력-은닉-출력(다층) 가중치/바이어스 1개(입력→출력) 2세트(입력→은닉, 은닉→출력) 순전파 한 번의 선형 연산+활성화 여러 층의 선형 연산+비선형 활성화 반복 학습 방식 출력층 오차로 단순 업데이트 역전파로 모든 층의 가중치/바이어스 업데이트 활성화 함수 계단함수/시그모이드(단순) 시그모이드/탄젠트 등(비선형, 미분 가능) 문제 해결력 선형 문제만 해결(XOR 불가) 비선형 문제(XOR 등) 해결 가능
Study
· 2025-06-26
Day3: Perceptron_MLP
# 📌 Perceptron이란? 1957년 프랭크 로젠브라트가 고안한 최초의 인공신경망 모델 중 하나. 생물학적 뉴런을 수학적으로 모델링한 인공 뉴런으로, 여러 입력 신호를 받아 각각의 가중치를 곱한 후 이를 합산하여, 활성화 함수를 통해 단일 신호를 출력한다. 퍼셉트론의 출력은 신호 유무 (1 또는 0)로 표현된고, 이진 분류 문제 해결에 효과적이다. 📝 Perceptron AND_GATE 실습 🔍 AND 게이트 모델 훈련 후 결과 확인 import numpy as np import matplotlib.pyplot as plt class Perceptron: def __init__(self, input_size, lr=0.1, epochs=10): self.weights = np.zeros(input_size) self.bias = 0 self.lr = lr self.epochs = epochs self.errors = [] def activation(self, x): return np.where(x >= 0, 1, 0) def predict(self, x): linear_output = np.dot(x, self.weights) + self.bias return self.activation(linear_output) def train(self, X, y): for epoch in range(self.epochs): total_error = 0 for x1, target in zip(X, y): prediction = self.predict(x1) update = self.lr * (target - prediction) self.weights += update * x1 self.bias += update total_error += int(update != 0) self.errors.append(total_error) print(f"Epoch {epoch+1}/{self.epochs}, Errors: {total_error}") # AND 게이트 데이터 X_and = np.array([[0,0],[0,1],[1,0],[1,1]]) y_and = np.array([0,0,0,1]) # 퍼셉트론 모델 훈련 ppn_and = Perceptron(input_size=2) ppn_and.train(X_and, y_and) # 예측 결과 확인 print("\nAND Gate Test:") for x in X_and: print(f"Input: {x}, Predicted Output: {ppn_and.predict(x)}") 💡 출력 결과 🔍 AND 게이트 결정 경계 시각화 from matplotlib.colors import ListedColormap def plot_decision_boundary(X, y, model): cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FF0000', '#0000FF']) h = .02 # mesh grid 간격 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, Z, cmap=cmap_light) # 실제 데이터 포인트 표시 plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=100, marker='o') plt.xlabel('Input 1') plt.ylabel('Input 2') plt.title('Perceptron Decision Boundary') plt.show() # AND 게이트 결정 경계 시각화 plot_decision_boundary(X_and, y_and, ppn_and) 💡 출력 결과 🔍 오류 시각화 plt.figure(figsize=(8, 5)) plt.plot(range(1, len(ppn_and.errors) + 1), ppn_and.errors, marker='o') plt.xlabel('Epochs') plt.ylabel('Number of Errors') plt.title('Perceptron Learning Error Over Epochs (AND Gate)') plt.grid(True) plt.show() 💡 출력 결과 📝 Perceptron OR_GATE 실습 🔍 OR 게이트 모델 훈련 후 결과 확인 import numpy as np import matplotlib.pyplot as plt class Perceptron: def __init__(self, input_size, lr=0.1, epochs=10): self.weights = np.zeros(input_size) self.bias = 0 self.lr = lr self.epochs = epochs self.errors = [] def activation(self, x): return np.where(x >= 0, 1, 0) def predict(self, x): linear_output = np.dot(x, self.weights) + self.bias return self.activation(linear_output) def train(self, X, y): for epoch in range(self.epochs): total_error = 0 for x1, target in zip(X, y): prediction = self.predict(x1) update = self.lr * (target - prediction) self.weights += update * x1 self.bias += update total_error += int(update != 0) self.errors.append(total_error) print(f"Epoch {epoch+1}/{self.epochs}, Errors: {total_error}") # OR 게이트 데이터 X_or = np.array([[0,0],[0,1],[1,0],[1,1]]) y_or = np.array([0,1,1,1]) # 퍼셉트론 모델 훈련 ppn_or = Perceptron(input_size=2) ppn_or.train(X_or, y_or) # 예측 결과 확인 print("\nOR Gate Test:") for x in X_or: print(f"Input: {x}, Predicted Output: {ppn_or.predict(x)}") 💡 출력 결과 🔍 OR 게이트 결정 경계 시각화 from matplotlib.colors import ListedColormap def plot_decision_boundary(X, y, model): cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FF0000', '#0000FF']) h = .02 # mesh grid 간격 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, Z, cmap=cmap_light) # 실제 데이터 포인트 표시 plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=100, marker='o') plt.xlabel('Input 1') plt.ylabel('Input 2') plt.title('Perceptron Decision Boundary') plt.show() # OR 게이트 결정 경계 시각화 plot_decision_boundary(X_or, y_or, ppn_or) 💡 출력 결과 🔍 오류 시각화 plt.figure(figsize=(8, 5)) plt.plot(range(1, len(ppn_or.errors) + 1), ppn_or.errors, marker='o') plt.xlabel('Epochs') plt.ylabel('Number of Errors') plt.title('Perceptron Learning Error Over Epochs (OR Gate)') plt.grid(True) plt.show() 💡 출력 결과 📝 Perceptron NAND_GATE 실습 🔍 NAND 게이트 모델 훈련 후 결과 확인 import numpy as np import matplotlib.pyplot as plt class Perceptron: def __init__(self, input_size, lr=0.1, epochs=10): self.weights = np.zeros(input_size) self.bias = 0 self.lr = lr self.epochs = epochs self.errors = [] def activation(self, x): return np.where(x >= 0, 1, 0) def predict(self, x): linear_output = np.dot(x, self.weights) + self.bias return self.activation(linear_output) def train(self, X, y): for epoch in range(self.epochs): total_error = 0 for x1, target in zip(X, y): prediction = self.predict(x1) update = self.lr * (target - prediction) self.weights += update * x1 self.bias += update total_error += int(update != 0) self.errors.append(total_error) print(f"Epoch {epoch+1}/{self.epochs}, Errors: {total_error}") # NAND 게이트 데이터 X_nand = np.array([[0,0],[0,1],[1,0],[1,1]]) y_nand = np.array([1,1,1,0]) # 퍼셉트론 모델 훈련 ppn_nand = Perceptron(input_size=2) ppn_nand.train(X_nand, y_nand) # 예측 결과 확인 print("\nNAND Gate Test:") for x in X_nand: print(f"Input: {x}, Predicted Output: {ppn_nand.predict(x)}") 💡 출력 결과 🔍 NAND 게이트 결정 경계 시각화 from matplotlib.colors import ListedColormap def plot_decision_boundary(X, y, model): cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FF0000', '#0000FF']) h = .02 # mesh grid 간격 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, Z, cmap=cmap_light) # 실제 데이터 포인트 표시 plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=100, marker='o') plt.xlabel('Input 1') plt.ylabel('Input 2') plt.title('Perceptron Decision Boundary') plt.show() # NAND 게이트 결정 경계 시각화 plot_decision_boundary(X_nand, y_nand, ppn_nand) 💡 출력 결과 🔍 오류 시각화 plt.figure(figsize=(8, 5)) plt.plot(range(1, len(ppn_or.errors) + 1), ppn_or.errors, marker='o') plt.xlabel('Epochs') plt.ylabel('Number of Errors') plt.title('Perceptron Learning Error Over Epochs (OR Gate)') plt.grid(True) plt.show() 💡 출력 결과 📝 Perceptron XOR_GATE 실습 🔍 XOR 게이트 모델 훈련 후 결과 확인 import numpy as np import matplotlib.pyplot as plt class Perceptron: def __init__(self, input_size, lr=0.1, epochs=10): self.weights = np.zeros(input_size) self.bias = 0 self.lr = lr self.epochs = epochs self.errors = [] def activation(self, x): return np.where(x >= 0, 1, 0) def predict(self, x): linear_output = np.dot(x, self.weights) + self.bias return self.activation(linear_output) def train(self, X, y): for epoch in range(self.epochs): total_error = 0 for x1, target in zip(X, y): prediction = self.predict(x1) update = self.lr * (target - prediction) self.weights += update * x1 self.bias += update total_error += int(update != 0) self.errors.append(total_error) print(f"Epoch {epoch+1}/{self.epochs}, Errors: {total_error}") # XOR 게이트 데이터 X_xor = np.array([[0,0],[0,1],[1,0],[1,1]]) y_xor = np.array([0,1,1,0]) # 퍼셉트론 모델 훈련 ppn_xor = Perceptron(input_size=2) ppn_xor.train(X_xor, y_xor) # 예측 결과 확인 print("\nXOR Gate Test:") for x in X_xor: print(f"Input: {x}, Predicted Output: {ppn_xor.predict(x)}") 💡 출력 결과 🔍 XOR 게이트 결정 경계 시각화 from matplotlib.colors import ListedColormap def plot_decision_boundary(X, y, model): cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FF0000', '#0000FF']) h = .02 # mesh grid 간격 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, Z, cmap=cmap_light) # 실제 데이터 포인트 표시 plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=100, marker='o') plt.xlabel('Input 1') plt.ylabel('Input 2') plt.title('Perceptron Decision Boundary') plt.show() # XOR 게이트 결정 경계 시각화 plot_decision_boundary(X_xor, y_xor, ppn_xor) 💡 출력 결과 🔍 오류 시각화 plt.figure(figsize=(8, 5)) plt.plot(range(1, len(ppn_or.errors) + 1), ppn_or.errors, marker='o') plt.xlabel('Epochs') plt.ylabel('Number of Errors') plt.title('Perceptron Learning Error Over Epochs (OR Gate)') plt.grid(True) plt.show() 💡 출력 결과 🚨 단층 Perceptron의 한계점 XOR GATE는 퍼셉트론으로 학습이 되지 않는 문제가 발생하였다. 퍼셉트론은 직선 하나로 ●와 ○를 나눌 수 있어야 학습이 된다. 하지만 XOR은 직선 하나로는 절대 ●와 ○를 나눌 수 없다.
Study
· 2025-06-25
Basic Operation
📝 학습목표 OpenCV(Open Source Computer Vision Library)를 활용하여 이미지/비디오 처리하기 1. 이미지 Read & Write 📂 이미지 파일 준비 import numpy as np import cv2 img = cv2.imread("image.jpg") cv2.namedWindow("image", cv2.WINDOW_NORMAL) print(img.shape) cv2.imshow("image", img) cv2.waitKey(0) cv2.imwrite("output.png", img) cv2.destroyAllWindows() 💡 출력 결과 2. 색상 채널 분리와 색공간 변환 📂 이미지 파일 준비 import numpy as np import cv2 color = cv2.imread("strawberry.jpg", cv2.IMREAD_COLOR) print(color.shape) height, width, channels = color.shape cv2.imshow("Original Image", color) r,g,b = cv2.split(color) rgb_split = np.concatenate((r,g,b), axis=1) cv2.imshow("RGB Channels", rgb_split) hsv = cv2.cvtColor(color, cv2.COLOR_RGB2HSV) h,s,v = cv2.split(hsv) hsv_split = np.concatenate((h,s,v),axis=1) cv2.imshow("Split HSV", hsv_split) cv2.waitKey(0) cv2.imwrite("hsv2rgb_split.png", hsv_split) 💡 출력 결과 3. 이미지 일부 영역 자르기, 크기 바꾸기, 회전하기 📂 이미지 파일 준비 import numpy as np import cv2 img = cv2.imread("image.jpg") print(img.shape) # 0,100 cropped = img[0:220, 185:385] #220, 200, 3 print(cropped.shape) resized = cv2.resize(cropped, (400,200)) print(resized.shape) rotated_90 = cv2.rotate(resized, cv2.ROTATE_90_CLOCKWISE) #rotated_180 = cv2.rotate(image, cv2.ROTATE_180) #rotated_270 = cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE) cv2.imshow("Origin", img) cv2.imshow("Cropped image", cropped) cv2.imshow("Resized image", resized) cv2.imshow("Rotated 90 image", rotated_90) cv2.waitKey(0) cv2.destroyAllWindows() 💡 출력 결과 cropped resized rotated_90 4. 원본 색상 반전시키기 📂 이미지 파일 준비 import numpy as np import cv2 src = cv2.imread("output.png", cv2.IMREAD_COLOR) dst = cv2.bitwise_not(src) cv2.imshow("src", src) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 5. 임계값 기준으로 이진화시키기 📂 이미지 파일 준비 import cv2 src = cv2.imread("image.jpg", cv2.IMREAD_COLOR) gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) ret, dst = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 6. 이미지 흐리게(블러) 처리 📂 이미지 파일 준비 import cv2 src = cv2.imread("image.jpg", cv2.IMREAD_COLOR) dst = cv2.blur(src, (9, 9), anchor=(-1, -1), borderType=cv2.BORDER_DEFAULT) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 7. 세 가지 대표적인 엣지(경계) 검출 알고리즘 📂 이미지 파일 준비 import cv2 src = cv2.imread("image.jpg", cv2.IMREAD_COLOR) gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, 3) cv2.imshow("sobel", sobel) laplacian = cv2.Laplacian(gray, cv2.CV_8U, ksize=3) cv2.imshow("laplacian", laplacian) canny = cv2.Canny(gray, 100, 200) cv2.imshow("canny", canny) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 sobel laplacian canny 8. 컬러 이미지의 BGR(Blue, Green, Red) 채널을 분리 후 채널 순서를 바꿔서 이미지 합치기 📂 이미지 파일 준비 import numpy as np import cv2 src = cv2.imread("image.jpg", cv2.IMREAD_COLOR) #b,g,r = cv2.split(src) b = src[:, :, 0] g = src[:, :, 1] r = src[:, :, 2] inverse = cv2.merge((r,g,b)) cv2.imshow("b", b) cv2.imshow("g", g) cv2.imshow("r", r) cv2.imshow("inverse", inverse) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 B G R inverse 9. 컬러 이미지의 BGR(Blue, Green, Red) 채널을 분리 후 Red 채널만 0(검정색) 📂 이미지 파일 준비 import numpy as np import cv2 src = cv2.imread("bgr.png", cv2.IMREAD_COLOR) b = src[:, :, 0] g = src[:, :, 1] r = src[:, :, 2] height, width, channel = src.shape zero = np.zeros((height, width, 1), dtype=np.uint8) bgz = cv2.merge((b, g, zero)) cv2.imshow("b", b) cv2.imshow("g", g) cv2.imshow("r", r) cv2.imshow("bgz", bgz) cv2.waitKey() cv2.destroyAllWindows() 💡 출력 결과 B G R bgz 10. 동영상에서 원하는 장면을 이미지로 캡처하기 📂 동영상 파일 준비 import numpy as np import cv2 import os save_dir = "SON" os.makedirs(save_dir, exist_ok=True) cap = cv2.VideoCapture("output.mp4") img_idx = 1 while cap.isOpened(): ret, frame = cap.read() if not ret: cap.set(cv2.CAP_PROP_POS_FRAMES, 0) continue height, width = frame.shape[:2] small_frame = cv2.resize(frame, (width // 2, height // 2), interpolation=cv2.INTER_AREA) cv2.imshow("Frame", small_frame) key = cv2.waitKey(80) if key & 0xFF == ord('q'): break if key & 0xFF == ord('c'): while True: filename = f"{img_idx:03d}.jpg" filepath = os.path.join(save_dir, filename) if not os.path.exists(filepath): cv2.imwrite(filepath, small_frame) print(f"Saved {filepath}") img_idx += 1 break else: img_idx += 1 cap.release() cv2.destroyAllWindows() 💡 출력 결과 11. 다양한 OpenCV 그리기 함수 사용해보기 import numpy as np import cv2 cap = cv2.VideoCapture(5) circle_centers = [] def draw_circle(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: circle_centers.append((x, y)) cv2.namedWindow("Camera") cv2.setMouseCallback("Camera", draw_circle) topLeft = (50, 50) bottomRight = (300, 300) while cap.isOpened(): ret, frame = cap.read() if not ret: break cv2.line(frame, topLeft, bottomRight, (0, 255, 0), 3) cv2.rectangle(frame, [pt+30 for pt in topLeft], [pt-30 for pt in bottomRight], (255, 0, 255), 3) font = cv2.FONT_ITALIC cv2.putText(frame, 'me', [pt+40 for pt in bottomRight], font, 2, (255, 0, 255), 5) for center in circle_centers: cv2.circle(frame, center, 30, (255, 255, 0), 3) cv2.imshow("Camera", frame) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() 💡 출력 결과 12. 실시간 카메라 영상 위에 글자 출력하고 트랙바로 굵기, 크기, 색상 조절하기 import numpy as np import cv2 cap = cv2.VideoCapture(4) #initial topLeft = (100, 100) bold = 0 font_size = 1 r, g, b = 0, 255, 255 def on_bold_trackbar(value): global bold bold = value def on_fontsize_trackbar(value): global font_size font_size = max(1, value) def on_r(val): global r r = val def on_g(val): global g g = val def on_b(val): global b b = val cv2.namedWindow("Camera") cv2.createTrackbar("bold", "Camera", bold, 10, on_bold_trackbar) cv2.createTrackbar("font size", "Camera", font_size, 10, on_fontsize_trackbar) cv2.createTrackbar('R', 'Camera', 0, 255, on_r) cv2.createTrackbar('G', 'Camera', 255, 255, on_g) cv2.createTrackbar('B', 'Camera', 255, 255, on_b) while cap.isOpened(): ret, frame = cap.read() if ret is False: print("Can't receive frame (stream end?). Exiting . . .") break # Text cv2.putText(frame, 'TEXT', topLeft, cv2.FONT_HERSHEY_SIMPLEX, font_size, (b, g, r), 1 + bold) # Display cv2.imshow("Camera", frame) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() 💡 출력 결과 13. 실시간 카메라 영상 위에 한글 출력하고 트랙바로 굵기, 크기, 색상 조절하기 import numpy as np import cv2 from PIL import ImageFont, ImageDraw, Image cap = cv2.VideoCapture(4) topLeft = (100, 100) bold = 0 font_size = 10 r, g, b = 0, 255, 255 def on_bold_trackbar(value): global bold bold = value def on_fontsize_trackbar(value): global font_size font_size = max(10, value * 5) def on_r(val): global r r = val def on_g(val): global g g = val def on_b(val): global b b = val cv2.namedWindow("Camera") cv2.createTrackbar("bold", "Camera", bold, 10, on_bold_trackbar) cv2.createTrackbar("font size", "Camera", font_size//5, 10, on_fontsize_trackbar) cv2.createTrackbar('R', 'Camera', 0, 255, on_r) cv2.createTrackbar('G', 'Camera', 255, 255, on_g) cv2.createTrackbar('B', 'Camera', 255, 255, on_b) font_path = "NanumGothic.ttf" while cap.isOpened(): ret, frame = cap.read() if not ret: print("Can't receive frame (stream end?). Exiting . . .") break img_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(img_pil) font = ImageFont.truetype(font_path, font_size) text = 'LEE 은성' # Bold 효과: 여러 번 겹쳐 그리기 for dx in range(-bold, bold+1): for dy in range(-bold, bold+1): draw.text((topLeft[0]+dx, topLeft[1]+dy), text, font=font, fill=(r, g, b, 0)) frame = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) cv2.imshow("Camera", frame) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() 💡 출력 결과
Study
· 2025-06-24
Day1: AI Algotirhm and Structure
Von Neumann Architecture 폰 노이만 구조 폰 노이만 병목 현상 하버드 구조 파이프라인 1. 폰 노이만 구조 폰 노이만 구조란? 폰 노이만 구조가 등장하기 전까지는 하드와이어드 프로그래밍 방식을 사용했다. 폰 노이만 구조가 등장하면서, 프로그램 내장 방식을 사용하게 되었고, 특징은 명령어와 데이터가 같은 메모리 공간에 저장되고 순차적으로 실행된다. 하드와이어드 프로그래밍 방식 : 폰 노이만 구조가 등장하기 전까지는 계산을 할 때마다 손으로 직접 진공관의 회로 스위치를 조정하여 새 입력을 처리하는 하드웨어 프로그램 방식 폰 노이만 구조의 주요 구성 요소 중앙처리장치(CPU) 메모리(Memory) 입출력장치(In.Out Device) 버스 시스템(Bus) 폰 노이만 구조의 동작 원리 폰 노이만 구조의 컴퓨터는 명령어 실행 사이클을 반복 동작한다. 명령어 인출(Fetch): 메모리에서 명령어를 가져온다. 명령어 해석(Decode): 메모리에서 가져온 명령어가 어떤 명령어인지 해석한다. 명령어 실행(Execute): 명령어를 실행한다. 메모리 연산(Data Memory): 명령어 수행을 위해 메모리와 데이터 레지스터 간의 데이터 이동을 처리 저장(WriteBack): 연산 결과를 메모리에 저장한다. //사진 넣기 2. 폰 노이만 구조의 병목 현상 폰 노이만 구조의 단점 폰노이만 구조의 가장 치명적인 단점은 폰노이만 병목현상이다. 단일 버스 구조 명령어와 데이터가 같은 버스를 공유하기 때문에 나타나는 현상이다. CPU는 한번에 명령어 또는 데이터를 가져올 수 있기 때문에 동시에 불가능하다. 메모리 벽 CPU의 성능은 기하급수적으로 발전했지만, 메모리의 속도가 그에 미치지 못해 이 속도 격차가 CPU의 대기 시간을 늘려 CPU의 제 성능을 발휘하지 못한다. 순차적 처리 명령어가 순차적으로 실행이 되는데, 이러한 처리 방식은 갈수록 데이터 종류가 다양해지고, 대규모 병렬 연산이 필요한 현대 사회에서는 비효율적이다. 폰 노이만 구조의 병목현상이 미치는 영향 상대적으로 메모리보다 빠른 CPU가 대부분의 시간을 메모리를 기다리게 되므로 시스템의 성능 저하로 이어진다. (CPU의 유후 시간 증가) 데이터가 CPU와 메모리를 왔다갔다하는 것이 전력 소모가 크다. -> 신호 전이(Transition)에 따른 전력 소모 버스에서 데이터가 0->1, 1->0으로 바뀔 때마다 transition이 발생 -> transition의 횟수가 많아질수록 전력 소모 증가 -> 캐패시터 충전과 방전 버스의 선로는 캐패시터 역할을 함 -> 데이터가 변경 될 때마다 커패시터를 충방전하게 된다 -> 더 빠른 스위칭을 위해서는 높은 과도 전류가 필요하게 되어 전력 소모가 증가하게 된다. 3. 하버드 구조 하버드 구조란? 폰 노이만 구조에서는 하나의 버스 시스템에서 데이터와 명령어가 이동했지만, 하버드 구조는 명령어와 데이터를 물리적으로 분리된 메모리에 저장하고 접근하는 구조이다. 폰 노이만 구조 vs 하버드 구조 하버드 구조에서는 폰 노이만 구조와 달리 명령어를 메모리로부터 읽는 것과 데이터를 메모리로부터 읽는 것을 동시에 할 수 있다. 하버드 구조는 병렬 처리를 통한 성능 향상이 가능하다. 현재 명령어를 처리함과 동시에 다음 명령어를 읽을 수 있다. (파이프라인) 하버드 구조 적용 사례 디지털 신호 처리기 (DSP)에서 주로 사용한다. 실시간 데이터 처리가 중요한 프로세서로, 하버드 구조의 병렬 메모리 접근 능력이 더 높은 메모리 대역폭을 제공하기 때문이다. 메모리 대역폭이란? -> 단위 시간당 전송 가능한 데이터의 양, 초당 얼마나 많은 비트(bit)를 주고받을 수 있는 지. -> CPU가 명령어를 인출하면서 동시에 데이터 메모리에서 연산에 필요한 데이터를 읽어올 수 있다. 즉, 두 개의 독립된 명령어 버스, 데이터 버스를 통해 동시에 전송이 가능하므로 전체 메모리 대역폭을 두배로 사용 가능.
Study
· 2025-06-23
<
>
Touch background to close