딥러닝 03 - 컨볼루셔널 신경망(CNN)

소개

CNN(Convolutional Neural Network)은 이미지 및 비디오 처리에 일반적으로 사용되는 딥러닝 모델입니다. 기존 신경망에 비해 CNN은 이미지의 특징을 자동으로 학습하고 가장 유용한 정보를 추출할 수 있기 때문에 이미지 및 시퀀스 데이터를 처리하는 능력이 더 좋습니다.

CNN의 핵심 기능은 이미지에 대해 슬라이딩 윈도우 계산을 수행하고 필터(컨볼루션 커널이라고도 함) 및 풀링 레이어(Max Pooling)를 통해 이미지 특징을 추출할 수 있는 컨볼루션 작업입니다. 컨볼루션 연산은 영상의 공간 구조 정보를 유지하면서 가중치 수와 계산량을 효과적으로 줄일 수 있습니다. 풀링 레이어는 특징 맵의 차원을 변경하지 않고도 계산량을 줄이고 모델의 견고성을 향상시킬 수 있습니다.

CNN의 일반적인 구조에는 컨볼루션 레이어, 풀링 레이어, 완전 연결 레이어 등이 포함됩니다. 동시에 과적합을 방지하기 위해 CNN은 Dropout 및 L2 정규화와 같은 일부 정규화 기술도 추가합니다.

CNN은 이미지 분류, 표적 탐지, 음성 인식 및 기타 분야에서 널리 사용됩니다. 이미지 분류 작업에서 CNN의 고전적인 모델에는 LeNet-5, AlexNet, VGG 및 GoogleNet/Inception이 포함됩니다. 이러한 모델의 설계 아이디어와 네트워크 구조는 다르지만 모두 컨볼루션 신경망 개발에 중요한 기여를 했습니다. 기여하다.

개발 경로

CNN(Convolutional Neural Network)은 이미지 인식, 컴퓨터 비전 및 기타 분야에서 널리 사용되는 딥러닝 모델입니다. CNN의 개발 과정에서 많은 클래식 모델이 등장했는데, 다음은 몇 가지 유명한 모델을 간략하게 소개합니다.

  1. 르넷-5

LeNet-5는 Yann LeCun과 다른 사람들이 1998년에 제안했으며 최초로 널리 사용된 컨벌루션 신경망 모델이었습니다. 주로 필기 숫자 인식에 사용되며 컨벌루션 레이어, 풀링 레이어, 완전 연결 레이어로 구성됩니다. LeNet-5의 설계를 통해 MNIST 필기 숫자 인식 작업에서 매우 우수한 성능을 달성할 수 있습니다. 컨볼루션 커널 개수(6, 16개)와 매개변수 개수가 적은 것이 특징이며, 첫 번째 컨볼루션 계층은 5×5 크기의 컨볼루션 커널 6개를 사용하고, 두 번째 컨볼루션 계층은 16A 크기의 컨볼루션 커널을 사용한다. 5×5. 이 설계는 모델의 매개변수 수를 효과적으로 줄일 수 있지만 컨볼루션 신경망의 창시자이며 후속 모델의 기반을 마련합니다.

  1. 알렉스넷

AlexNet은 2012년 Alex Krizhevsky 등이 제안했습니다. ImageNet 이미지 분류 대회에서 우수한 결과를 얻은 최초의 컨볼루션 신경망 모델이었습니다. 다중 컨볼루션 레이어와 풀링 레이어를 사용하고 ReLU 활성화 기능과 Dropout 정규화 기술을 사용합니다. AlexNet의 설계는 ImageNet 이미지 분류 경쟁에서 다른 모델보다 훨씬 앞서게 하여 컨볼루셔널 신경망 개발의 새로운 라운드를 주도했습니다. 많은 수의 컨볼루션 커널(약 6,000개)과 많은 수의 매개변수를 사용하는 것이 특징이지만 정확성과 효율성 측면에서 좋은 성능을 가지고 있습니다.

  1. VGG

VGG는 2014년 Karen Simonyan과 Andrew Zisserman에 의해 제안되었습니다. VGG의 주요 기여는 더 큰 컨볼루션 커널 대신 더 작은 컨볼루션 커널(3x3)의 사용을 제안하는 것입니다. 이 설계는 네트워크를 더 깊게 만들고 매개변수를 줄여 효율성과 정확성을 향상시킵니다. VGG에는 16개 또는 19개의 컨볼루셔널 레이어와 풀링 레이어가 포함되어 있으며 이러한 레이어는 모두 동일한 컨볼루션 커널 크기와 스트라이드를 사용합니다. VGG는 ImageNet 이미지 분류 경쟁에서 매우 좋은 결과를 얻었으며 후속 ResNet 및 기타 모델에도 영감을 제공했습니다.

  1. 구글넷/인셉션

GoogleNet은 2014년 Google 팀에 의해 제안되었습니다. 주요 기여는 매개변수의 양을 늘리지 않고도 네트워크의 깊이와 너비를 늘릴 수 있는 Inception 모듈입니다. Inception 모듈은 기능 추출을 위해 다양한 크기의 여러 컨볼루션 커널과 풀링 레이어를 사용한 다음 이를 서로 연결하여 모듈을 형성합니다. GoogleNet은 또한 완전 연결 레이어 대신 전역 평균 풀링 레이어를 사용하여 매개변수 수를 더욱 줄입니다. GoogleNet은 ImageNet 이미지 분류 대회에서 매우 좋은 결과를 얻었으며 후속 ResNet, DenseNet 및 기타 모델에 영감을 제공했습니다.

  1. 레스넷

ResNet은 2015년 Microsoft Research Asia 팀에 의해 제안되었습니다. ResNet의 주요 기여는 심층 합성곱 신경망의 성능 저하 문제를 해결할 수 있는 잔여 학습을 제안하는 것입니다. 성능 저하 문제는 네트워크의 깊이가 깊어질수록 정확도가 감소하는 현상을 말합니다. 잔여 학습은 입력을 출력으로 직접 전송하는 교차 계층 연결을 도입하여 정보 손실을 방지합니다. ResNet은 더 깊은 네트워크 구조(152개 레이어)를 포함하지만 정확도가 더 높습니다. ResNet의 디자인 아이디어는 후속 DenseNet, MobileNet 및 기타 모델에서 계승되었습니다.

  1. DenseNet

DenseNet은 Gao Huang et al.이 2017년에 제안했습니다. DenseNet의 주요 기여는 네트워크의 깊이와 폭을 늘려 효율성과 정확성을 향상시킬 수 있는 조밀한 연결을 제안하는 것입니다. 조밀한 연결(Dense Connection)은 각 레이어의 출력을 모든 후속 레이어의 입력에 연결하여 조밀한 연결 구조를 형성하는 것을 의미합니다. 이 설계는 신경망을 더 컴팩트하게 만들고, 매개변수가 더 적으며, 기능의 재사용성을 향상시킬 수도 있습니다. DenseNet은 ImageNet 이미지 분류 경쟁에서 매우 좋은 결과를 얻었으며 ShuffleNet 및 EfficientNet과 같은 후속 모델에도 영감을 제공했습니다.

  1. 모바일넷

MobileNet은 2017년 Google 팀에서 제안했습니다. 주요 기여는 우수한 정확도를 유지하면서 매개변수 수를 줄일 수 있는 깊이 분리 가능한 컨볼루션을 제안하는 것입니다. 깊이별 분리형 컨볼루션(Depthwise separable convolution)은 컨볼루션 연산을 깊이 컨볼루션과 포인트별 컨볼루션의 두 단계로 나누어 계산량과 매개변수를 줄이는 것을 말합니다. MobileNet은 깊이 분리 가능한 여러 컨벌루션 레이어와 풀링 레이어를 사용하여 모바일 장치와 같이 리소스가 제한된 환경에서 효율적인 이미지 분류 및 대상 탐지를 달성합니다. MobileNet의 디자인 아이디어는 ShuffleNet 및 EfficientNet과 같은 후속 모델에서 계승되었습니다.

  1. ShuffleNet

ShuffleNet은 2018년 Microsoft Research Asia 팀에 의해 제안되었습니다. 주요 기여는 정확성을 유지하면서 매개 변수 및 계산의 양을 크게 줄일 수 있는 채널 재구성 및 그룹 컨볼루션을 제안하는 것입니다. 채널 재구성은 서로 다른 그룹 간의 정보 교환을 허용하기 위해 입력 채널을 그룹화 및 재그룹화하는 것을 의미합니다. 그룹 컨볼루션이란 컨볼루션 연산을 그룹 내 컨볼루션과 그룹 간 컨볼루션의 두 단계로 나누어 계산량과 매개 변수를 줄이는 것을 말합니다. ShuffleNet은 다중 채널 재구성 및 그룹 컨벌루션 레이어를 사용하여 리소스가 제한된 환경에서 효율적인 이미지 분류 및 대상 탐지를 달성합니다.

  1. EfficientNet

EfficientNet은 2019년 Google 팀에서 제안했습니다. 주요 기여는 정확도를 유지하면서 매개변수 및 계산의 양을 크게 줄일 수 있는 네트워크 스케일링 및 복합 계수를 제안하는 것입니다. 네트워크 스케일링은 모델 구조를 변경하지 않고 최적화하기 위해 네트워크의 깊이, 너비 및 해상도를 동시에 스케일링하는 것을 의미합니다. 복합 계수는 보다 효율적인 모델을 얻기 위해 깊이, 너비 및 해상도의 스케일링 계수를 결합하는 것을 의미합니다. EfficientNet은 ImageNet 이미지 분류 대회에서 매우 좋은 결과를 얻었으며 후속 모델 최적화에 대한 영감도 제공했습니다.

  1. RegNet

RegNet은 2020년 Facebook AI 연구팀에 의해 제안되었습니다. 주요 기여는 정확성을 유지하면서 매개변수 및 계산의 양을 크게 줄일 수 있는 네트워크 구조에 대한 적응형 규칙을 제안하는 것입니다. 적응형 규칙은 보다 효율적인 모델을 얻기 위해 검색 및 최적화를 통해 네트워크 구조의 하이퍼 매개변수를 자동으로 조정하는 것을 말합니다. RegNet은 ImageNet 이미지 분류 경쟁에서 매우 좋은 결과를 얻었으며 후속 모델 최적화에 대한 영감도 제공했습니다.

위의 모델은 잘 알려진 몇 가지 컨볼루션 신경망 모델로, 설계 아이디어와 네트워크 구조는 다르지만 모두 컨볼루션 신경망 개발에 중요한 기여를 했습니다.

도식적 원리

컨벌루션 신경망은 이미지 인식 분야에서 빛을 발하며 전례 없는 정확도를 달성하고 다양한 응용 분야를 보유하고 있습니다. 다음으로는 컨볼루션 신경망의 원리를 소개하기 위해 이미지 인식을 예로 들어보겠습니다.

사례

주어진 그림(문자 X 또는 문자 O)이 아래 그림과 같이 CNN을 사용하여 X인지 O인지 식별할 수 있다고 가정합니다. 어떻게 해야 할까요?
여기에 이미지 설명을 삽입하세요.

이미지 입력

전통적인 신경망 모델을 사용하는 경우 전체 이미지를 신경망 모델의 입력으로 읽어야 합니다(즉, 완전 연결). 이미지의 크기가 커지면 그에 연결된 매개 변수가 많아지게 되어 결과적으로 계산량이 많아 매우 큽니다.
외부 세계에 대한 인간의 인식은 일반적으로 지역적 부분에서 전체적 부분으로 진행되며, 먼저 지역적인 부분에 대한 지각적 이해를 갖고 점차적으로 전체에 대한 인식을 얻게 됩니다.이것이 인간 이해 모델입니다. 이미지의 공간적 연결은 유사하며, 로컬 범위의 픽셀은 밀접하게 연결되어 있는 반면, 멀리 있는 픽셀 간의 상관 관계는 약합니다. 따라서 각 뉴런은 실제로 전체 이미지를 인식할 필요가 없으며 로컬 부분만 인식한 다음 상위 수준에서 로컬 정보를 합성하여 전체 정보를 얻으면 됩니다. 이 모드는 컨벌루션 신경망(국소 수용 필드)의 매개변수 수를 줄이는 데 중요한 인공물입니다.
여기에 이미지 설명을 삽입하세요.

특징 추출

문자의 경우 예를 들어 아래 그림과 같이 Translation, Scaling, Rotation, Micro-Deformation 등이 있을 경우:
여기에 이미지 설명을 삽입하세요.
우리의 목표는 CNN을 통해 다양한 형태학적 변화에서 X와 O를 정확하게 식별하는 것인데, 이는 어떻게 효과적으로 특징을 추출할 수 있는지, 식별의 주요 요소로 사용됩니다.
앞에서 언급한 "로컬 수용 필드" 모드를 떠올려 보세요. CNN의 경우 작은 조각을 비교하고 두 이미지의 대략 동일한 위치에서 대략적인 특징(작은 이미지 패치)을 찾는 것입니다. 매칭을 위해 전통적인 비교와 비교합니다. 전체 이미지를 하나씩, CNN의 작은 블록 매칭 방법을 사용하면 두 이미지 간의 유사성을 더 잘 비교할 수 있습니다. 아래 그림과 같이
여기에 이미지 설명을 삽입하세요.
문자를 검정색으로 취하면
여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

위의 특징 추출은 가정이며, 실제로 입력된 이미지가 여러 개인 경우 컨볼루션 신경망은 각 이미지에 대한 특징을 추출합니다.구체적인 프로세스는 입력 이미지가 첫 번째 컨볼루션 레이어를 통과한 후 컨볼루션을 수행하는 것입니다. 커널이 이미지에 있을 것입니다. 가장자리, 모서리 등과 같은 일부 낮은 수준의 특징을 추출하려면 위로 스와이프하세요.

컨볼루션 신경망에서 여러 개의 서로 다른 컨볼루션 커널을 사용하는 경우 각 컨볼루션 커널의 로컬 수용 필드 크기는 동일하지만 서로 다른 컨볼루션 커널의 가중치가 다르기 때문에 각 컨볼루션 커널은 서로 다른 기능을 학습합니다.

예를 들어 컨볼루션 계층에서 세 가지 다른 컨볼루션 커널을 사용한다고 가정합니다. 여기서 첫 번째 컨볼루션 커널의 가중치는 가장자리를 감지하는 데 사용되고 두 번째 컨볼루션 커널의 가중치는 텍스처 특징을 감지하는 데 사용되며 세 번째 컨볼루션의 가중치는 커널은 에지를 감지하는 데 사용되며 컨볼루션 커널의 가중치는 대상의 모양을 감지하는 데 사용됩니다. 이 세 컨볼루션 커널의 로컬 수용 필드는 모두 동일한 크기이지만 가중치가 다르기 때문에 각 컨볼루션 커널은 서로 다른 기능을 학습할 수 있습니다.

컨볼루션 커널의 크기와 단계 크기는 각 컨볼루션 커널의 로컬 수용 필드 크기에도 영향을 미친다는 점에 유의해야 합니다. 컨볼루션 커널의 크기가 더 크면 그에 따라 로컬 수용 필드도 커지며, 스텝 크기가 더 크면 컨볼루션 커널이 매번 슬라이드하는 거리도 그에 따라 커지므로 컨볼루션 커널에 영향을 줍니다. 로컬 수용 필드.

예를 들어 컨벌루션 커널
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]]

이 행렬은 실제로 Sobel 필터라고도 알려진 컨볼루션 커널입니다. 이미지의 수직 가장자리를 감지하는 데 사용할 수 있습니다.
컴퓨터 비전에서 가장자리는 회색 값의 큰 변화가 있는 이미지의 영역을 나타냅니다. 수직 가장자리는 이미지의 상단에서 하단으로, 하단에서 상단으로 회색 값의 변화를 나타냅니다.
컨볼루션 커널의 작동 원리는 이미지의 픽셀과 컨벌루션하여 이미지의 특징을 추출하는 것입니다. 이 예에서 컨볼루션 커널의 중심 요소는 0이며 이는 이미지의 중심 픽셀과 관련이 없음을 나타냅니다. 컨볼루션 커널의 요소 [-1, 0, 1]의 위쪽 행은 이미지의 위쪽 픽셀과 컨볼루션 작업을 수행함을 나타냅니다. 마찬가지로 컨볼루션 커널의 아래쪽 행에 있는 요소 [-1, 0, 1]은 이미지의 하위 픽셀과 컨볼루션 작업을 수행함을 나타냅니다.

컨볼루션 커널이 이미지의 픽셀과 컨볼루션될 때 이미지에 수직 가장자리가 있으면 컨볼루션 결과에 뚜렷한 변화가 나타납니다. 구체적으로, 수직 가장자리의 한쪽에서는 컨볼루션 결과가 더 큰 양수 값을 얻고, 수직 가장자리의 다른 쪽에서는 컨벌루션 결과가 더 큰 음수 값을 얻습니다. 이런 방식으로 임계값 컨볼루션 결과를 통해 이미지의 수직 가장자리를 식별할 수 있으며 음수 부분은 직접 0으로 반환됩니다.

예를 들어, 일부가 수직 가장자리인 이미지가 있다고 가정해 보겠습니다. 이 이미지의 수직 가장자리 부분에 컨볼루션 커널을 적용하면 컨볼루션 결과가 양수와 음수 값을 나타내므로 컨볼루션 결과를 임계값화하여 수직 가장자리의 위치를 ​​추출할 수 있습니다.

이 예제가 행렬 [-1, 0, 1]을 사용하여 수직 가장자리를 감지할 수 있는 이유를 이해하는 데 도움이 되기를 바랍니다.
또 다른 예로
[[-0.1111, -0.1111, -0.1111],
[-0.1111, 1.0000, -0.1111],
[-0.1111, -0.1111, -0.1111]] 등이 있는데
이를 라플라시안 필터(Laplacian filter) 또는 샤프닝 필터(sharpening filter)라고 한다. 이미지의 가장자리를 향상시키는 데 사용할 수 있습니다.
이 행렬에서 중심 요소 1은 이미지의 중심 픽셀과 관련이 있음을 의미합니다. 그리고 주변 요소 -0.1111은 이미지의 주변 픽셀과 관련이 있음을 의미합니다.

컨벌루션 커널이 이미지와 컨볼루션되면 중앙 픽셀의 값이 증폭되고 주변 픽셀의 값은 억제됩니다. 이러한 방식으로 이미지의 가장자리에서는 픽셀 값의 큰 변화로 인해 컨볼루션 결과가 더 큰 양수 및 음수 값을 나타내므로 가장자리의 대비가 향상됩니다.

예를 들어 일부 가장자리가 포함된 이미지가 있다고 가정해 보겠습니다. 이 컨볼루션 커널을 이미지에 적용하면 컨볼루션 결과로 가장자리의 대비가 향상되어 더 선명해집니다.

따라서 이 컨볼루션 커널은 가장자리를 감지하고 가장자리의 대비를 강화하여 가장자리를 더 명확하게 만들 수 있습니다.

가장자리

엣지는 영상 속 픽셀의 회색값이 크게 변하는 곳으로, 일반적으로 영상 속 물체의 모서리, 윤곽, 질감 등의 정보를 나타낸다. 이미지 처리 및 컴퓨터 비전에서 가장자리 감지는 이미지 분할, 특징 추출 등에 사용할 수 있는 일반적으로 사용되는 기술입니다.
예를 들어 아래와 같이
여기에 이미지 설명을 삽입하세요.
Edge Extraction의 효과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

각점

모서리 점은 각도 변화가 뚜렷한 이미지의 국소 영역에 있는 특수 점입니다. 모서리 점은 일반적으로 서로 다른 방향의 모서리가 교차하여 형성되며 가우시안 곡률을 가지며 이미지의 중요한 특징 중 하나입니다. 코너 감지는 이미지 등록, 객체 추적, 이미지 매칭 등에 일반적으로 사용되는 기술이기도 합니다. 일반적으로 사용되는 코너 감지 알고리즘에는 Harris 코너 감지, Shi-Tomasi 코너 감지 등이 있습니다.
아래 그림과 같이
여기에 이미지 설명을 삽입하세요.

opencv

OpenCV(오픈 소스 컴퓨터 비전 라이브러리)는 오픈 소스 컴퓨터 비전 및 기계 학습 소프트웨어 라이브러리입니다. 이는 개발자가 이미지 처리, 객체 감지, 얼굴 인식, 비디오 분석 등과 같은 컴퓨터 비전 애플리케이션을 신속하게 구축하는 데 도움이 될 수 있습니다.

OpenCV는 원래 Intel Corporation에서 시작되었으며 이제는 C++, Python, Java 등을 포함한 여러 프로그래밍 언어를 지원하고 Windows, Linux, macOS 등과 같은 운영 체제에서 실행될 수 있는 크로스 플랫폼 오픈 소스 프로젝트가 되었습니다.

여기서는 Opencv를 사용하여 특정 그림의 가장자리와 모서리를 추출합니다. 예를 들어 그림은 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

여기서는 opencv에 대해 자세히 다루지 않고 이 기사의 뒷부분에서 설명하겠습니다.
암호

#%%
import cv2  #注意安装open-cv  conda install open-cv
import numpy as np
import matplotlib.pyplot as plt

# 读入lena图像
img = cv2.imread('d:/9.png')
# 将BGR图像转换为RGB图像,便于matplotlib显示
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gray_ori=gray
# 使用Canny边缘检测函数检测图像的边缘
edges = cv2.Canny(gray, 100, 200)

# 创建SIFT对象
sift = cv2.xfeatures2d.SIFT_create()
# 检测图像的特征点
keypoints = sift.detect(gray, None)
# 在图像上绘制特征点
img_sift = cv2.drawKeypoints(img, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 检测图像的角点
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 将角点标记为红色
img_corner = img.copy()
img_corner[dst > 0.01 * dst.max()] = [255, 0, 0]

# 创建一个Matplotlib窗口并显示图像及其各种特征
plt.rcParams['font.family'] = 'SimHei'
fig, axs = plt.subplots(2, 2, figsize=(10, 10))
axs[0, 0].imshow(img)
axs[0, 0].set_title('原始图像')
axs[0, 1].imshow(edges, cmap='gray')
axs[0, 1].set_title('边缘')
axs[1, 0].imshow(img_sift)
#SIFT的全称是Scale Invariant Feature Transform,尺度不变特征变换。具有旋转不变性、尺度不变性、亮度变化保持不变性,是一种非常稳定的局部特征。
axs[1, 0].set_title('SIFT特征')
axs[1, 1].imshow(img_corner)
axs[1, 1].set_title('角点特征')
plt.show()

출력 효과
여기에 이미지 설명을 삽입하세요.

특징 추출 원리

[컨볼루션] 장을 읽은 후 이 섹션을 읽어보시기 바랍니다.
일반적으로 사용되는 컨볼루션 커널은 다음과 같습니다.

  1. 가우시안 필터: 이미지 스무딩에 사용되며 이미지 노이즈를 줄일 수 있습니다.
  2. 고역 통과 필터: 가장자리, 모서리 등과 같은 이미지의 고주파수 정보를 강조하는 데 사용됩니다.
  3. 저역 통과 필터: 흐림, 스무딩 등과 같은 이미지의 저주파 정보를 강조하는 데 사용됩니다.
  4. Sobel 필터: 이미지의 가장자리 정보를 감지하는 데 사용됩니다.
  5. 라플라시안 필터: 가장자리, 디테일 등과 같은 이미지의 고주파 정보를 향상시키는 데 사용됩니다.
  6. Scharr 필터: Sobel 필터와 유사하지만 가장자리에 더 반응합니다.
  7. Prewitt 필터: Sobel 필터와 유사하지만 가장자리에 대한 반응이 더 부드럽습니다.

이러한 컨볼루션 커널은 가장자리 감지, 이미지 스무딩, 이미지 향상 등과 같은 이미지 처리의 다양한 작업에 사용될 수 있습니다. 다양한 작업을 기반으로 이미지를 처리하기 위해 적절한 컨볼루션 커널을 선택할 수 있습니다.

아래에 정의된 컨볼루션 커널은 중앙 픽셀에 더 큰 가중치가 부여되고 주변 픽셀에 더 작은 가중치가 부여되므로 고역 통과 필터로 간주할 수 있습니다. 이러한 가중치 분포를 통해 컨볼루션 커널은 가장자리, 모서리 등과 같은 이미지의 고주파수 정보를 감지할 수 있습니다. 컨볼루션 연산에서는 컨볼루션 커널에 이미지의 각 픽셀을 곱하고 그 결과를 더해 새로운 픽셀 값을 얻습니다. 컨볼루션 커널의 중심 픽셀 주변의 픽셀 값과 중심 픽셀 값의 차이가 크면 컨볼루션 연산의 결과가 더 커지게 되어 이 픽셀이 에지 포인트일 수 있음을 나타냅니다. 따라서 이 컨볼루션 커널은 이미지의 가장자리 정보를 강조할 수 있습니다.

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])

다음 그림이 있는데,
여기에 이미지 설명을 삽입하세요.
opencv를 사용하여 로드하고 컨볼루션 커널로 컨벌루션합니다.

import cv2
import numpy as np
from myutils.common import show,fillColor
# 读取图片
img = cv2.imread('./images/z.png')

# 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 定义卷积核
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
# kernel = np.array([[-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1], [-1,-1,20,-1,-1],[-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1]])
# kernel = cv2.getGaussianKernel(5, 1)

# 对灰度图像进行卷积操作,#注意如果-1 <0的值会被归一化为0
edges = cv2.filter2D(gray, cv2.CV_32F, kernel)
print(edges[:][edges<0])
# 对卷积结果进行ReLU处理
edges_relu = np.maximum(0, edges)
show(img,'Original Image',cmap="gray",debug=True)  
show(edges, 'Edges Image',cmap="gray",debug=True)
show(edges_relu, 'Edges ReLU Image',cmap="gray",debug=True)

def show(dilate, title, cmap=None, debug=False):
    if debug:
        plt.title(title)
        plt.imshow(dilate, cmap=cmap)
        plt.show()

여기에 이미지 설명을 삽입하세요.

Convolution 연산이 relu를 사용하는 대신 선형 특징을 추출한다고 말하는 이유는 무엇입니까?

컨볼루션 작업 자체로는 비선형 특징을 추출할 수 없음을 설명하기 위해 간단한 예를 들어 보겠습니다.

다음 값을 포함하는 입력 행렬 X가 있다고 가정합니다.

X = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

이제 2x2 크기의 컨볼루션 커널 K를 사용하여 X를 컨볼루션합니다. 컨볼루션 커널의 값은 다음과 같습니다.

K = [[1, 1], [1, 1]]

행렬 곱셈을 사용하여 컨볼루션 작업을 수행할 수 있습니다. 구체적으로, K 행렬을 뒤집고 X 행렬과 내적 연산을 수행하여 출력 행렬 Y를 얻습니다.

Y = K*X = [[12, 16], [24, 28]]

출력 행렬 Y는 입력 행렬 X의 선형 결합이므로 컨볼루션 연산 자체로는 입력 행렬 X의 가장자리, 텍스처 등 선형 특징만 추출할 수 있음을 알 수 있습니다.

그러나 ReLU 활성화 함수와 같은 비선형 활성화 함수를 사용하여 출력 행렬 Y를 처리하면 선형 특징을 비선형 특징으로 변환할 수 있습니다. 예를 들어 ReLU 함수를 Y에 적용하면 결과적인 비선형 특성은 다음과 같습니다.

ReLU(Y) = [[12, 16], [24, 28]]

따라서 컨볼루션 연산 자체로는 입력 행렬의 선형 특징만 추출할 수 있지만, 비선형 활성화 함수와 결합하면 비선형 특징을 추출할 수 있습니다.

회선

그렇다면 일치를 위해 이러한 기능은 어떻게 계산됩니까? (픽셀이 하나씩 일치한다고 말하지 마세요, 땀!)
이때 오늘의 중요한 게스트인 컨볼루션을 초대해야 합니다. 그럼 컨볼루션이란 무엇일까요? 아래에서 천천히 설명드릴테니 걱정하지 마세요.
새로운 이미지가 제공되면 CNN은 이러한 특징이 일치해야 하는 원본 이미지의 어느 부분을 정확히 알지 못하므로 원본 이미지에서 가능한 모든 위치를 시도합니다. 이는 이 특징을 필터로 바꾸는 것과 같습니다. 이러한 매칭 과정을 컨볼루션 연산(Convolution Operation)이라고 하는데, 이는 컨볼루션 신경망(Convolutional Neural Network)이라는 이름의 유래이기도 합니다.
컨볼루션 작업은 아래 그림과 같습니다.
여기에 이미지 설명을 삽입하세요.


노란색 부분은 컨볼루션 커널입니다. 즉, 이전 그림 [[1,0,1]
[0,1,0]
[1,0,1]] 에서 추출한 특징은
다음의 가능한 모든 3*과 동일합니다. 3개의 이미지를 계산하고(동일한 위치의 컨볼루션을 곱한 후 더함 / 현재 집계 행렬의 수는 9), 계산 결과는 현재 컨볼루션의 중심에 위치한 숫자이며, 최종적으로 다음과 같이 새로운 이미지를 얻습니다. 가장 바깥쪽 레이어가 제거되었습니다.행렬의 구체적인 계산 논리는 다음을 참조하십시오.

이 경우 원본 이미지에서 특징(feature)과 이에 대응하는 특정 작은 패치의 결과를 계산하려면 두 개의 작은 패치에서 해당 위치의 픽셀 값을 곱한 다음 곱하기만 하면 됩니다. 전체 작은 패치 작업 결과는 누적되고 최종적으로 작은 블록의 총 픽셀 수로 나뉩니다(참고: 총 수로 나눌 필요는 없습니다).
두 픽셀이 모두 흰색(둘 다 1의 값을 가짐)이면 1 1 = 1이고, 둘 다 검정색이면 (-1) (-1) = 1입니다. 즉, 각 픽셀 쌍이 일치할 수 있으므로 곱셈 결과는 다음과 같습니다. 1입니다. 마찬가지로, 일치하지 않는 픽셀에는 -1이 곱해집니다. 구체적인 프로세스는 다음과 같습니다(첫 번째, 두 번째..., 마지막 픽셀의 일치 결과).
먼저 컨볼루션을 위해 이전에 추출한 세 가지 특징 중 하나를 사용합니다
여기에 이미지 설명을 삽입하세요.
. 예를 들어 첫 번째 특징에 녹색 프레임으로 동그라미를 칩니다. 부품 비교 컨볼루션의 계산 방법에 따르면 1차 특징 매칭 이후의 컨볼루션 계산은 다음과 같으며
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
결과는 1 이다 . 세 가지 특징 이미지에 대해서는 위의 과정을 지속적으로 반복하고, 각 특징(feature)의 컨볼루션 연산을 통해 새로운 2차원 배열을 얻게 되는데 이를 특징 맵(feature map)이라고 합니다 . 값이 1에 가까울수록 해당 위치와 지형지물이 완전하게 일치하는 것을 의미하며, -1에 가까울수록 해당 위치와 지형지물의 반대면이 완전하게 일치하는 값입니다. 가 0에 가까울수록 해당 위치와 특징이 더 완벽하게 일치함을 의미하며, 값이 0에 가까울수록 해당 위치와 특징이 더 완벽하게 일치함을 의미합니다. 아래 그림과 같이 이미지 크기가 증가하면 내부 덧셈, 곱셈, 나눗셈 연산의 수가 매우 빠르게 증가하고 각 필터의 ​​크기와 필터 수가 선형적으로 증가하는 것을 볼 수 있습니다. 너무 많은 요인이 작용하면 계산량이 상당히 커질 수 있습니다.
여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

풀링

계산량을 효과적으로 줄이기 위해 CNN이 사용하는 또 다른 효과적인 도구는 "풀링(Pooling)"입니다. 풀링은 입력 이미지를 축소하고 픽셀 정보를 줄이며 중요한 정보만 유지하는 것입니다.
풀링의 조작도 매우 간단합니다.보통 풀링 영역의 크기는 2 2 이며, 최대값(max-pooling)과 평균(mean)을 취하는 등 특정 규칙에 따라 해당 값으로 변환됩니다. pooling 영역에서 -pooling) 등에서 이 값을 결과 픽셀 값으로 사용합니다.
아래 그림은
좌측 상단의 2 2 pooling 영역에 대한 max-pooling 결과를 보여주며, 아래 그림과 같이 이 영역의 최대 max(0.77,-0.11,-0.11,1.00)를 pooling 결과로 취한다. : 왼쪽의 풀링 영역
여기에 이미지 설명을 삽입하세요.
, 두 번째 작은 블록은 아래와 같이 풀링 결과로 최대값 max(0.11, 0.33, -0.11, 0.33)를 취합니다.
여기에 이미지 설명을 삽입하세요.
다른 영역도 비슷하며 다음과 같이 영역의 최대값을 취합니다. 풀링 결과, 그리고 마지막으로 풀링 후 결과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.
모든 특징 맵에 대해 동일한 작업을 수행하면 결과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.
max-pooling은 각 작은 블록의 최대값을 유지합니다. 이 블록의 최고 값 일치 결과(값이 1에 가까울수록 더 나은 일치를 의미하므로) 즉, 창의 어느 위치가 일치하는지 구체적으로 초점을 맞추지 않고 어딘가에 일치하는 부분이 있는지 여부에만 초점을 맞춥니다.
풀링 레이어를 추가하면 이미지가 줄어들어 계산량을 크게 줄이고 머신 부하를 줄일 수 있습니다.

활성화 기능 ReLU(수정 선형 단위)

일반적으로 사용되는 활성화 함수에는 sigmoid, tanh, relu 등이 있습니다. 처음 두 개인 sigmoid/tanh는 완전 연결 계층에서 더 일반적이고 후자인 ReLU는 컨벌루션 계층에서 일반적입니다.
앞서 언급한 퍼셉트론을 다시 살펴보면, 퍼셉트론은 각 입력을 받아 합산한 뒤 활성화 함수를 거친 뒤 출력한다. 활성화 함수의 기능은 비선형 요소를 추가하고 컨볼루션 레이어의 출력 결과에 대해 비선형 매핑을 수행하는 것입니다.
여기에 이미지 설명을 삽입하세요.
컨벌루션 신경망에서 활성화 함수는 일반적으로 빠른 수렴과 간단한 기울기 계산이 특징인 ReLU(The Rectified Linear Unit, Modified Linear Unit)를 사용합니다. 계산식도 매우 간단합니다. max(0,T)입니다. 즉, 음수 입력 값의 경우 출력이 모두 0이고 양수 값의 경우 출력이 변경되지 않습니다.
이 경우 ReLU 활성화 함수의 연산 과정을 살펴보면
아래와 같이 첫 번째 값을 max(0,0.77)로 취하고 결과는 0.77이고, 두
여기에 이미지 설명을 삽입하세요.
번째 값을 max(0, -0.11), 아래 그림과 같이 결과는 0입니다. 그림
여기에 이미지 설명을 삽입하세요.
비유하자면 ReLU 활성화 함수를 통과한 후 결과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.
모든 특징 맵에 대해 ReLU 활성화 함수 연산을 실행하면 결과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

심층 신경망

위에서 언급한 컨볼루션, 활성화 함수, 풀링을 결합하면 다음과 같은 그림이 됩니다.
여기에 이미지 설명을 삽입하세요.
네트워크의 깊이를 늘리고 레이어를 추가하면 아래와 같은 심층 신경망이 얻어집니다.
여기에 이미지 설명을 삽입하세요.

완전 연결 레이어

완전 연결 계층은 컨벌루션 신경망 전체에서 '분류자' 역할을 합니다. 즉, 컨볼루션, 활성화 함수, 풀링 등의 심층 네트워크를 거친 후 결과를 완전 연결 계층을 통해 식별하고 분류합니다.
먼저 컨볼루션, 활성화 함수, 풀링을 거친 딥 네트워크의 결과는 아래 그림과 같이 연결됩니다.
여기에 이미지 설명을 삽입하세요.
신경망은 지도 학습에 속하므로 모델 훈련 시에는 훈련 샘플을 기반으로 모델을 훈련하여 완전 연결을 얻습니다 레이어의 가중치(예: 문자를 예측하는 모든 연결의 가중치)
여기에 이미지 설명을 삽입하세요.
계산된 결과에 가중치를 부여하고 합산하여 각 결과의 예측 값을 얻은 다음 가장 큰 값을 인식 결과로 취합니다(그림 참조). 아래 그림에서 최종 계산된 문자 X의 인식값은 0.92이고, 문자 O의 인식값은 0.51이므로 결과는 다음과 같이 판단된다
여기에 이미지 설명을 삽입하세요.
.
여기에 이미지 설명을 삽입하세요.

컨볼루셔널 신경망

위의 모든 결과를 하나로 묶으면 아래 그림과 같이 "CNN(Convolutional Neural Network)" 구조가 형성됩니다. 마지막으로 검토
여기에 이미지 설명을 삽입하세요.
및 요약하면 Convolutional Neural Network는 주로 두 부분으로 구성되며, 한 부분은 특징 추출입니다. (콘볼루션, 활성화 함수, 풀링), 나머지 부분은 분류 인식(완전 연결 레이어)입니다. 다음 그림은 유명한 필기 텍스트 인식 콘볼루션 신경망 구조 다이어그램입니다.
여기에 이미지 설명을 삽입하세요.

이 장의 내용에 대한 참조: https://my.oschina.net/u/876354/blog/1620906

컨볼루션 API

Conv2D

Conv2D는 Convolutional Neural Network의 핵심 레이어 중 하나로, 이미지나 기타 2차원 데이터의 Convolution 처리에 사용되는 레이어입니다. Conv2D의 기능은 입력된 2차원 이미지나 데이터에 대해 컨볼루션 커널을 통해 일련의 컨볼루션 연산을 수행하여 이미지나 데이터의 특징을 추출하는 것입니다.

Conv2D 레이어의 입력은 텐서이며, 텐서의 형태는 보통 (batch_size, height, width, Channel)인데, 여기서 Batch_size는 입력 데이터의 개수를 나타내고, height와 width는 입력 데이터의 높이와 너비를 나타내고, 채널은 입력 데이터의 채널 수를 나타냅니다.(예를 들어 RGB 이미지의 채널 수는 3입니다.)

Conv2D 레이어의 출력도 텐서이며, 이는 컨볼루션 작업 후에 얻은 특징 맵을 나타냅니다. 출력 텐서의 모양은 일반적으로 (batch_size, conv_height, conv_width,filters)이며, 여기서 conv_height와 conv_width는 컨볼루션 커널을 적용한 후 얻은 기능 맵의 높이와 너비를 나타내고 필터는 컨볼루션 커널의 수, 즉 , 출력 특징 맵의 채널 수.

컨볼루션 과정에서 Conv2D 계층은 컨볼루션 커널을 입력 데이터에 적용하고, 각 컨볼루션 커널과 입력 데이터 간의 컨볼루션 연산을 하나씩 계산하여 컨볼루션된 출력 특징 맵을 얻습니다. 컨볼루션 프로세스 중에 컨볼루션 커널의 크기, 단계 크기 및 채우기 방법과 같은 매개변수를 자유롭게 설정하여 다양한 애플리케이션 시나리오에 적응할 수 있습니다.
TensorFlow 2.0 및 Keras에서는 다음 코드를 사용하여 Conv2D 레이어를 생성할 수 있습니다.

from tensorflow.keras.layers import Conv2D

conv_layer = Conv2D(filters=32, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu', input_shape=(height, width, channel))
  • 필터: 컨볼루션 커널 수, 즉 출력 특성 맵 수입니다.
  • kernel_size: 컨볼루션 커널의 크기로, 정사각형 컨볼루션 커널의 측면 길이를 나타내는 정수이거나 길이와 너비가 다른 컨볼루션 커널을 나타내는 튜플일 수 있습니다.
  • strides: stride는 컨볼루션 커널이 입력 기능 맵에서 이동하는 거리입니다. 두 개의 인접한 컨볼루션 커널 사이의 거리를 나타내는 정수일 수도 있고, 길이와 너비 방향에서 단계 크기가 다르다는 것을 나타내는 튜플일 수도 있습니다.
  • padding: 패딩 방법은 '동일' 또는 '유효'일 수 있습니다. '동일하다'는 것은 출력 특징맵의 크기가 입력 특징맵의 크기와 같고, 입력 특징맵 주위에 일부 값을 채워야 한다는 뜻이고, '유효하다'는 패딩이 필요하지 않다는 뜻이고, 출력 기능 맵의 크기는 입력 기능 맵과 컨볼루션 커널을 기반으로 하며 크기에 따라 다릅니다.
  • 활성화: 기능 맵에 비선형 변환을 추가하는 데 사용되는 활성화 함수입니다. 일반적인 활성화 함수로는 'relu', 'sigmoid', 'tanh' 등이 있습니다.
  • input_shape: 입력 특징 맵의 모양으로, 높이, 너비, 채널 수를 나타내는 삼중항일 수 있습니다. 이 매개변수는 첫 번째 컨벌루션 레이어에서 지정되어야 합니다.
  • kernel_regularizer: 딥러닝에서는 모델의 과적합을 방지하기 위해 정규화 기술을 사용하여 모델을 제한하는 경우가 많으며, 일반적으로 사용되는 정규화 방법 중 하나가 L2 정규화입니다. L2 정규화는 모델 가중치의 크기를 제한하기 위해 모델의 손실 함수에 L2 표준 페널티 항을 추가하는 것을 의미합니다.
    Keras에서는 Regularizers.l2(0.001)를 사용하여 L2 정규화 페널티를 추가합니다. 그 중 0.001은 정규화의 강도를 제어하는 ​​정규화 매개변수입니다. 정규화 매개변수가 클수록 페널티 항이 가중치에 미치는 영향이 커지고 모델의 복잡성이 줄어들어 과적합을 효과적으로 방지할 수 있습니다.
    특히, Regularizers.l2(0.001)는 완전 연결 레이어, 컨볼루션 레이어 등과 같은 신경망의 모든 가중치 행렬에 적용될 수 있습니다. 네트워크 정의에서 해당 레이어의 kernel_regularizer 매개변수를 사용하여 L2 정규화를 추가할 수 있습니다. 예를 들어 Keras에서 L2 정규화를 사용하여 완전 연결 계층을 추가하는 코드는 다음과 같습니다.
layers.Conv2D(32, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape=(28, 28, 1)),

컨볼루션 예

minist10 사진을 찍고 컨볼루션을 위해 10개의 컨볼루션 커널을 사용하여 특징 맵을 출력하고 이미지를 표시합니다.
각 사진은 10개의 컨볼루션 커널을 생성하므로 총 100개의 특징 맵이 생성됩니다.

#%%
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np

# 加载mnist数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 取1张训练集图片
images = train_images[:10]

# 将图片转换为float类型
images = images.astype('float32') / 255.0
# 将图片reshape成4D张量,大小为(10, 28, 28, 1),也就是第一个维度表示有10张图像,每张图像由28行、28列和1个# 通道(灰度)组成
images = np.expand_dims(images, axis=3)
# 定义卷积核数量
num_filters = 10

# 定义卷积层
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(num_filters, (3, 3), activation='relu', input_shape=(28, 28, 1)),
])

# 计算卷积后的特征图
features = model.predict(images)

# 绘制卷积后的特征图
fig, axs = plt.subplots(nrows=num_filters, ncols=10, figsize=(10, num_filters))
for i in range(num_filters):
    for j in range(10):
        axs[i][j].imshow(features[j, :, :, i], cmap='gray')
        axs[i][j].axis('off')
plt.show()

산출
여기에 이미지 설명을 삽입하세요.

np.expand_dims 함수는 지정된 축에서 배열의 크기를 확장하는 데 사용됩니다. 이 예에서 이미지는 10개의 28x28 회색조 이미지를 나타내는 모양(10, 28, 28)의 배열입니다. 그러나 기계 학습 모델은 일반적으로 4차원 배열, 즉 (샘플 수, 이미지 높이, 이미지 너비, 채널 수)를 입력해야 합니다. 따라서 이미지 배열의 마지막 차원(채널 수)을 1차원 확장하여 모양(10, 28, 28, 1)의 배열로 변환해야 합니다.
구체적으로 axis=3은 배열의 세 번째 축(0부터 계산)의 차원을 확장하는 것을 의미합니다. 이는 각 이미지의 마지막 차원에 1차원을 추가하여 각 이미지를 (28, 28, 1) 3- 차원 배열. 마지막으로 이미지 배열의 모양은 (10, 28, 28, 1)이 됩니다. 이는 10개의 28x28 회색조 이미지가 있고 각 이미지가 하나의 채널로 구성됨을 의미합니다. 이런 방식으로 이미지를 기계 학습 모델의 입력으로 전달할 수 있습니다.

위의 출력 그림에서 볼 수 있듯이 일부 컨볼루션 커널의 출력은 가장자리, 일부 모서리 및 일부 텍스처로 편향되어 있습니다.

MaxPooling2D

keras.layers.MaxPooling2D((2, 2))는 최대 풀링 작업에 사용되는 Keras의 레이어입니다.
최대 풀링(Maximum Pooling)은 이미지 크기를 변경하지 않고 이미지의 매개변수 수를 줄여 계산량과 메모리 소비를 줄일 수 있는 일반적으로 사용되는 컨벌루션 신경망 연산입니다. 최대 풀링 연산은 입력 이미지를 겹치지 않는 블록으로 나누고 각 블록의 최대값을 출력으로 사용합니다. 컨볼루션 신경망에서 최대 풀링은 일반적으로 이미지의 공간적 특징을 추출하기 위해 컨볼루셔널 레이어와 같은 의미로 사용됩니다.

MaxPooling2D 계층의 매개변수는 튜플(2, 2)이며, 이는 풀링 창의 크기가 2x2임을 나타냅니다. 이는 입력 이미지가 2x2 크기의 여러 블록으로 분할되고 각 블록의 최대값이 출력으로 사용됨을 의미합니다. 풀링 창 크기가 (3, 3)으로 설정된 경우 입력 이미지는 3x3 크기의 여러 블록으로 분할되고 각 블록의 최대값이 출력으로 사용됩니다.

간단히 말해서, MaxPooling2D 레이어는 컨벌루션 신경망이 이미지의 공간적 특징을 추출하는 동시에 계산량과 메모리 소비를 줄이는 데 도움이 될 수 있습니다.

단조롭게 하다

keras.layers.Flatten()은 입력을 1차원 벡터로 "평탄화"하는 데 사용되는 Keras의 레이어입니다.

합성곱 신경망에서는 일반적으로 이미지의 특징을 추출하기 위해 합성곱 레이어와 풀링 레이어를 사용하고, 분류를 위해 완전 연결 레이어를 사용합니다. 완전 연결 레이어의 입력은 1차원 벡터이므로 이전 특징 맵을 1차원 벡터로 "평탄화"해야 합니다. 이것이 Flatten 레이어의 역할입니다.

Flatten 레이어에는 매개변수가 없으며 입력 텐서를 순서대로 1차원 벡터로 펼칩니다. 예를 들어 입력 텐서의 모양이 (batch_size, 7, 7, 64)인 경우 Flatten 레이어의 출력 모양은 (batch_size, 7 7 64 )입니다.

컨벌루션 신경망을 구축할 때 일반적으로 컨벌루션 계층과 풀링 계층 뒤에 Flatten 계층을 추가하여 특징 맵을 1차원 벡터로 평탄화한 다음 이를 완전 연결 계층에 연결하여 분류합니다.

밀도|드롭아웃

다층 퍼셉트론 참조

필기 숫자 인식

컨볼루셔널 Mnist 데이터세트

MNIST 데이터세트를 로드하고 전처리하고, 픽셀 값을 0과 1 사이로 조정하고, 데이터세트를 훈련 세트와 테스트 세트로 분할하겠습니다. 데이터 처리에 대한 자세한 설명은 다층 퍼셉트론을
참조하세요 .

import tensorflow as tf
import tensorflow.keras
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import regularizers
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

num_classes = 10

y_train = tf.keras.utils.to_categorical(y_train, num_classes)
y_test = tf.keras.utils.to_categorical(y_test, num_classes)

다음으로 컨볼루셔널 신경망 모델을 정의하겠습니다. 우리는 두 개의 컨볼루션 레이어와 두 개의 풀링 레이어를 사용하고, 두 개의 완전 연결 레이어와 출력 레이어를 사용할 것입니다. 또한 과적합을 방지하기 위해 드롭아웃과 L2 정규화를 사용할 것입니다.

model = tf.keras.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.Dropout(0.5),
    layers.Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.Dropout(0.5),
    layers.Dense(num_classes, activation='softmax')
])

model.summary()는 Keras의 모델 객체 메소드로, 각 레이어 이름, 출력 모양, 매개변수 수 등을 포함한 모델의 구조 정보를 출력하는 데 사용됩니다. 이는 모델 디버깅, 최적화 및 모델 구조 이해에 유용합니다.

model.summary()

그런 다음 모델을 컴파일하고 데이터 확대 기술을 사용하여 과적합을 더욱 방지합니다. 데이터 증강 기술은 회전, 변환, 크기 조정 등과 같은 일련의 무작위 변환을 적용하여 새로운 훈련 샘플을 생성합니다. 이는 모델을 더욱 강력하게 만들고 과적합을 방지합니다.

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

datagen = ImageDataGenerator(
    rotation_range=10,
    width_shift_range=0.1,
    height_shift_range=0.1,
    zoom_range=0.1
)

다음으로 훈련 세트를 사용하여 모델을 훈련하고 테스트 세트를 사용하여 모델 성능을 평가하겠습니다.

datagen.fit(x_train)
batch_size = 1024
epochs = 10
checkpoint = tf.keras.callbacks.ModelCheckpoint('./model.h5', save_best_only=True, save_weights_only=False, monitor='val_loss')
history = model.fit(datagen.flow(x_train, y_train, batch_size=batch_size),
                    epochs=epochs,
                    validation_data=(x_test, y_test),
                    steps_per_epoch=len(x_train) // batch_size,callbacks=[checkpoint])

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

steps_per_epoch와 배치_크기의 차이점은
배치_크기는 각 훈련 배치(batch)에 포함된 샘플 수를 의미한다는 점입니다. 딥러닝에서 훈련 세트는 일반적으로 여러 배치로 나뉘며, 각 배치에는 여러 샘플이 포함됩니다. 이것의 장점은 행렬 연산을 사용하여 계산 속도를 높일 수 있고, 과적합을 방지하기 위해 훈련 과정에서 샘플의 순서를 무작위로 혼란시킬 수도 있다는 것입니다.

steps_per_epoch는 한 에포크에서 모델을 훈련해야 하는 배치 수를 나타냅니다. 각 에포크에는 여러 개의 배치가 포함되어 있으므로 단계에 몇 개의 배치를 전달해야 하는지 지정하려면 steps_per_epoch를 설정해야 합니다. 일반적으로 steps_per_epoch의 값은 훈련 세트 크기와 배치_크기로부터 계산할 수 있습니다. 예를 들어 훈련 세트 크기가 1000이고 배치_크기가 32인 경우 한 에포크에서 1000/32 = 31개의 배치를 훈련해야 하므로 steps_per_epoch를 31로 설정해야 합니다.

steps_per_epoch가 훈련 세트 크기를 배치_크기로 나눈 값과 반드시 ​​같지는 않다는 점에 유의해야 합니다. 훈련 세트 크기가 배치_크기로 나누어지지 않는 경우 마지막 배치에는 배치_크기보다 적은 샘플이 포함될 수 있습니다. 이러한 상황을 피하기 위해 // 하향 반올림 연산을 사용하여 steps_per_epoch를 계산하여 각 epoch에서 전체 훈련 세트가 처리될 수 있도록 할 수 있습니다.

미세 조정

미세 조정(Fine-tuning)은 더 나은 성능을 얻기 위해 특정 작업이나 특정 데이터 세트에 대해 이미 훈련된 모델을 미세 조정하는 방법을 말합니다. 일반적으로 ImageNet 및 기타 데이터 세트와 같은 대규모 데이터 세트에 대해 사전 훈련된 모델을 사용합니다. 이 모델은 훈련 과정에서 많은 공통 기능과 패턴을 학습했습니다. 이 모델을 미세 조정하고, 일부 매개변수를 조정하거나, 새 레이어를 추가하여 이 모델을 새로운 작업이나 새로운 데이터 세트에 더 적합하게 만들 수 있습니다. 이 접근 방식은 사전 훈련된 모델이 이미 좋은 초기 가중치와 특징 추출 기능을 갖추고 있기 때문에 일반적으로 모델을 처음부터 훈련하는 것보다 더 효율적입니다.

mnist-c 데이터 세트

MNIST-C는 MNIST 데이터 세트에 인공 잡음이 추가된 MNIST 데이터 세트의 변형입니다. MNIST 데이터 세트는 60,000개의 훈련 샘플과 10,000개의 테스트 샘플을 포함하는 필기 숫자 인식 데이터 세트이며, 각 샘플은 28 x 28 픽셀 회색조 이미지입니다. MNIST-C 데이터 세트는 MNIST 데이터 세트의 이미지에 임의의 노이즈를 추가하여 생성되며, 이러한 노이즈에는 흐림, 왜곡, 밝기 변화 등이 포함되어 모델을 더욱 견고하게 만듭니다.

MNIST-C 데이터세트는 다양한 유형의 노이즈에 대한 모델의 견고성을 테스트할 수 있기 때문에 머신러닝 모델의 견고성을 테스트하는 데 매우 유용합니다. MNIST-C 데이터 세트의 각 이미지에는 해당 이미지가 나타내는 숫자를 나타내는 레이블이 포함되어 있습니다. 이러한 레이블은 MNIST 데이터 세트의 해당 레이블과 동일하므로 동일한 훈련 및 테스트 프로세스를 사용하여 모델을 훈련하고 테스트할 수 있습니다.

https://github.com/google-research/mnist-c/에서 데이터 세트를 다운로드하세요. 이 github 주소는 소스 코드 주소입니다. 실제 다운로드 주소는 readme에 언급되어 있습니다: https://zenodo.org/record /3239543# .ZF2rzXZByUl, 다운로드 및 압축 풀기
여기에 이미지 설명을 삽입하세요.
이 폴더는 모두 npy 형식의 numpy 배열 내보내기입니다.
표시할 각 폴더의 처음 10개 사진을 읽습니다.

# 数据集的开源地址:https://github.com/google-research/mnist-c/
import os
import numpy as np
import matplotlib.pyplot as plt
#加载数据集并打印每个子文件夹前10个数据集
data_root = './mnist_c'
dirlist=os.listdir(data_root)
fig, axs = plt.subplots(len(dirlist), 10, figsize=(10, 10))

for i, folder_name in enumerate(dirlist):
    folder_path = os.path.join(data_root, folder_name)
    if os.path.isdir(folder_path):
        file_path = os.path.join(folder_path, 'train_images.npy')
        data = np.load(file_path)
        for j in range(0,10):
            axs[i, j].imshow(data[j].reshape(28,28), cmap='gray')
            axs[i, j].axis('off')
plt.tight_layout()
plt.show()

산출
여기에 이미지 설명을 삽입하세요.

미세 조정 방법 교육

./model.h5에서 훈련된 minist 모델을 시험하기 시작한다고 가정하면 모델을 로드한 다음 minist-c 데이터 훈련을 계속하기 위해 모델을 시험해야 합니다.

#%%

import os
import numpy as np
import tensorflow.keras as layers
import tensorflow as tf
import datetime

TARGET_MODEL_DIR="./"
MODEL_NAME="model.h5"
epochs_count=5
"""
   jupyter打印的日志太大导致ipynb打开很慢,这里写个一模一样代码的py运行
"""
def againTrain(x_train, y_train, x_test, y_test):
    targetModel=os.path.join(TARGET_MODEL_DIR,MODEL_NAME)
    #记载CNN模型
    model=tf.keras.models.load_model(targetModel)
    """
    在使用Fine-tuning方法微调预训练模型时,通常会冻结模型的前几层,只调整模型的后面几层,这是因为:
    1.预训练模型的前几层通常是针对原始数据集的通用特征提取器,这些特征对于不同的任务和数据集都是有用的,因此我们可以直接保留这些特征提取器,不需要进行微调。
    2.预训练模型的后几层通常是针对特定任务进行的微调,这些层的参数需要根据具体任务和数据集进行调整,以使模型更好地适应特定的任务和数据集。
    3.如果我们将整个模型的所有层都进行微调,会导致训练时间较长,而且可能会出现过拟合等问题。因此,冻结前几层可以有效地减少训练时间,并提高模型的泛化能力。
    总之,冻结模型的前几层可以节省计算资源和训练时间,同时还可以提高模型的泛化能力,使其更好地适应新的任务和数据集。
    """
    model.layers[0].trainable = False
    model.layers[1].trainable = False
    # 对输入图像进行预处理
    x_train = x_train.reshape(-1, 28, 28, 1)
    x_train = x_train.astype('float32') / 255.0
    x_test = x_test.reshape(-1, 28, 28, 1)
    x_test = x_test.astype('float32') / 255.0
    y_train = tf.keras.utils.to_categorical(y_train, num_classes=10)
    y_test = tf.keras.utils.to_categorical(y_test, num_classes=10)
    now = datetime.datetime.now()  # 获取当前时间
    format_time = now.strftime("%Y-%m-%d%H-%M-%S")  # 转换为指定格式
    checkpoint = tf.keras.callbacks.ModelCheckpoint(targetModel, save_best_only=True, save_weights_only=False, monitor='val_loss')
    # 继续训练模型
    history = model.fit(x_train, y_train, batch_size=128, epochs=epochs_count, validation_data=(x_test, y_test),
                        callbacks=[checkpoint])
    test_loss, test_acc = model.evaluate(x_test, y_test)
    print('Test accuracy:', test_acc)
"""
  传入mnist-c,数据会非常大加载数据很慢,这里每加载一份子目录就训练一次,节省内存开销。
"""
def loadDataMnistC(data_root,func):
    dirlist=os.listdir(data_root)
    for i, folder_name in enumerate(dirlist):
        folder_path = os.path.join(data_root, folder_name)
        if os.path.isdir(folder_path):
            print("开始读取:"+folder_path)
            train_images = np.load(os.path.join(folder_path, 'train_images.npy'))
            train_labels = np.load(os.path.join(folder_path, 'train_labels.npy'))
            test_images = np.load(os.path.join(folder_path, 'test_images.npy'))
            test_labels = np.load(os.path.join(folder_path, 'test_labels.npy'))
            print("开始训练:"+folder_path)
            func(train_images,train_labels,test_images,test_labels)
            print("训练完成:"+folder_path)
# 加载 MNIST-C 数据集
data_root = './mnist_c'
model=None;
loadDataMnistC(data_root,againTrain)
print("全部训练完成")

여기서는 매번 특정 유형을 한 번씩 읽은 후 해당 모델을 하위 폴더에 다시 기록하여 학습하며, 학습이 완료될 때까지 최종 모델을 얻습니다.

추천

출처blog.csdn.net/liaomin416100569/article/details/130597944