반응형

딥러닝 신경망 스터디 중 MNIST 데이터셋을 만났다.

그리고 파이썬 피클(python pickle)이 나타났다.

 

 

MNIST 데이터셋

인공지능 머신러닝 분야에서 유명한 데이터셋이라고 한다.

손으로 쓴 숫자에 대한 인식에 필요한 필수 자료라고 한다.

딥러닝 실습은 해당 이미지와 데이터를 다운 받아야 한다.

전부터 유명한 사이트에 가서 다운로드를 시도했다.

그런데 파일이 없다.

gz파일 4개를 다운받아야 하는데 없다.

다행히도 Apache SystemDB 사이트에서 찾았다.

오픈 소스 머신러닝 시스템에 대한 사이트로 해당 파일을 다운로드할 수 있다.

MNIST 데이터셋 gz파일 4개

위 파일에 손으로 쓴 숫자에 대한 인식 테스트를 할 수 있는 데이터가 있다.

혼련 이미지 6만 장과 시험 이미지 1만 장이 포함되어 있다고 한다.

그렇다면 딥러닝 신경망을 위한 4개의 gz 파일은 어떻게 사용할까?

파이썬(Python)에서 직렬화(Serialization)를 지원하는 pickle(피클)이 있다.

4개의 gz 파일들은 피클링(직렬화)으로 하나의 피클(pickle) 파일로 만들면 된다.

1개로 만들어진 직렬화된 pickle 파일을 파이썬(Python)으로 쉽게 사용할 수 있다.

 

pickle 파일?

정의를 살펴보면 파이썬(python)에서만 사용하고 객체 직렬화를 하는 모듈이라고 한다.

피클링을 직렬화라고도 하는데 직렬화(serialization)는 또 무엇인가?

 

직렬화(Serialization)

프로그램을 실행하면 컴퓨터 메모리에 저장되고 사용된다.

컴퓨터 메모리는 전원을 끄면 사라지는 휘발성 공간이다.

메모리에 저장된 데이터, 객체를 별도로 저장하거나 다른 시스템에 보내는 경우가 있다.

컴퓨터 메모리 특성상 영구 저장이나 다른 시스템에 공유가 안된다.

꺼내서 저장하거나 전달해야 한다.

저장하거나 전달할 때 특정 형식이 필요하다. 예를 들어 바이너리, 스트림 형식.

바로 이런 형식으로 변환하는 과정을 직렬화라고 한다. 

다시 사용할 수 있게 만드는 과정은 역 직렬화라고 한다.

요즘 많이 사용하는 JSON도 직렬화의 하나다.

이게 무슨 말인가? 싶기도 하다.

나도 처음 자바(java)에서 직렬화를 보고 이해하는데 시간이 좀 걸렸었다.

이해하기 쉽게 예를 들어보자.

가구 전시장에 있는 전시된 장롱을 할인받아 구매했다. (데이터 구조, 객체)

크기가 너무 커서 일단 분해해서 배송을 한다. (피클링, 직렬화)

집에 도착해서 다시 조립한다. (역 피클링)

이런 느낌?

 

파이썬 전용 직렬화, 피클 (pickle)

파이썬(python)과 넘파이(numpy)에서 사용하는 배열, 튜플 그리고 클래스 객체.

이렇게 데이터 구조와 객체를 별도 파일에 저장할 때 필요하다.

마찬가지로 파이썬 데이터 구조나 객체를 저장하고 전송하고 싶다면 그대로는 안된다.

이동할 수 있는 형태로 변환해 주는 직렬화( Serialization ), 피클이 필요하다.

파이썬 피클(python pickle)은 바이너리 형태로 저장된다.

그래서 파일을 메모장에 열어도 알 수 없는 문자로 가득할 것이다.

mnist.pkl 파일, 바이너리로 변환되어 읽을 수 없다

이렇게 변환된 데이터는 파일로 저장하거나 메모리 또는 데이터베이스(DB)에 전달 가능하다.

저장하거나 보냈다면,

다시 꺼내 사용하거나 네트워크로 받았다면 원래 상태로 변환해서 사용해야 한다.

다시 말해 피클링(직렬화)으로 저장한 데이터를 시스템에서 사용하기 위해 다시 역 피클링한다는 의미다.

MNIST 데이터셋에 피클(직렬화)이 왜 필요하지?

MNIST 데이터셋을 사용하게 위해 성격이 다른 4개의 gz 파일을 받았다.

프로그램에서 사용하기 위해서는 매번 압축도 풀고 4개의 파일을 컨트롤해야 한다.

4개의 파일을 데이터셋 형태로 하나의 피클(pickle)에 저장하면 속도도 빠르다.

또한 파일로 저장해서 언제든 꺼내 사용할 수 있다.

인공지능 머신러닝, 딥러닝의 학습용 실습을 위해서 피클(pickle)은 기본이다.

 

피클링과 역 피클링 예제.

파이썬 피클(Python pickle)로 파일을 만들고 사용하는 방법을 보자.

import pickle


my_data = {'이름':'나쉐프', '나이':40, '소모품':['도마','칼','접시']}

#my_data 피클 파일을 dump로 생성.
with open('my_data.pkl', 'wb') as f:
    pickle.dump(my_data, f, -1)

print('my_data.pkl이 생성되었다')

file_path = './my_data.pkl'

try:
    with open(file_path, 'rb') as rf:
        get_data = pickle.load(rf)
        #my_data 피클 파일을 다시 읽기.
        print('get data : ', get_data)

except FileNotFoundError:
    print(f"오류: '{file_path}' 파일을 찾을 수 없다.")
except Exception as e:
    print(f"오류발생 : {e}")

'''
실행결과
my_data.pkl이 생성되었다
get data :  {'이름': '나쉐프', '나이': 40, '소모품': ['도마', '칼', '접시']}
'''

윈도우 탐색기로 로컬 폴더를 보면 pkl 확장자 파일이 생성됨을 볼 수 있다.

이 파일을 다시 load 하면 저장한 데이터가 그대로 출력된다.

 

pickle 모듈은 안전하지 않다.

이건 뭔 소린가?

파이썬(python) 사이트에서 pickle를 찾아보면 다음과 같은 경고문구를 만나게 된다.

https://docs.python.org/3/library/pickle.html 참조

신뢰할 수 없는 pickle 파일은 함부로 언 피클 하지 말라고 되어 있다.

왜?

 

pickle과 os.system

그래서 궁금했다.

피클이 얼마나 위험한지 다음 소스를 보고 확인해 봤다.

python pickle과 os.system 코드

위 코드를 실행하면 현 위치에 temp 폴더가 생성된다.

"놀랍지 않은가?"

누군가 만든 피클(pickle) 파일을 로드했을 뿐인데 내 컴퓨터에 폴더가 생성됐다.

파일 복사, 생성 등 뭐든 가능하다는 의미다.

즉, 누군가 악의적인 소스를 담은 피클 파일을 머신러닝 테스트 데이터로 가장해서 만들었다 가정하자.

이 파일을 다운로드하고 언 피클링, 로드한 순간 끔찍한 상황이 생길 것이다.

그래서 신뢰할 수 없는 피클 파일은 함부로 로딩하지 말아야겠다.

 

정리.

이제 피클(pickle)에 대해 알았고,

직렬화(serialization)에 대해 이해했고,

피클 주의 사항도 알게 되었다.

다시 딥러닝의 세계로 빠져들자~

 

잘못된 정보가 있으면 댓글 주세요.

반응형
반응형

다차원 배열(행렬)은 딥러닝에서 신경망 구현시 필수로 알아야 하는 부분이다.

배열(Array)이나 행렬은 프로그래밍 언어나 수학을 배울 때 들어봤을 것이다.

딥러닝에서 신경망에도 다차원 배열이 꼭 필요하다고 한다.

어렵지 않으니 기본 개념부터 하나씩 같이 살펴보자.

딥러닝 신경망 다차원 배열 (행렬)

다차원 배열과 행렬

C나 자바 같은 프로그래밍 공부를 했다면 배열(Array)을 배웠을 것이다.

파이썬 딥러닝은 넘파이(Numpy)에서 배열(Array)을 지원한다.

np는 import numpy as np 에서

숫자 1부터 5까지 같은 데이터타입(숫자)을 만든다.

2차원 배열은 어떻게 만들까?

2×3 배열(행렬)

1차원 배열과 달리 2차원 배열은 [1,2,3]과 [4,5,6]을 []로 한 번 더 구분했다.

 

딥러닝 신경망을 구현하려면 배열로 된 행렬의 연산이 필요하다.

위 1차원 2차원 배열을 행렬로 표시하면 아래와 같다.

딥러닝 신경망 다차원 배열 (행렬)

2차원 배열부터 다차원 배열(행렬)이라 한다.

행렬은 뭘까? 행과 열을 의미한다.

행과 열 = 행렬

가로로 보는 행이 2줄이다. 1 2와 3 4.

세로도 열이 2줄이다. 1 3과 2 4.

가로는 행 세로는 열이라고 한다.

그래서 행렬이다.

위 행렬은 행이 2개 열이 2개라 2 × 2 행렬이라고 부른다.

 

행렬 곱셈 하는 방법

딥러닝 신경망에서 다차원 배열(행렬)이 필요하다.

그러기 위해서 행렬의 곱셈을 알아야 한다.

그 이유는 뒤에 나온다.

우선 학교 다닐 때 배운 행렬의 곱에 대해 살펴보자.

행렬 곱셈

× 2 행렬 두 개를 곱하는 식이다.

곱하는 방법은 아래와 같다.

1. 첫 번째 행렬의 1행과 두 번째 행렬의 1열을 곱한다.

2. 1 × 5 + 2 × 7 = 19로 1행 1열의 값이 된다.

3. 첫 번째 행렬의 1행과 두 번째 행렬의 2열을 곱한다.

4. 1 × 6 + 2 × 8 = 22로 1행 2열의 값이 된다.

5. 첫 번째 행렬의 2행과 두 번째 행렬의 1열을 곱한다.

6. 3 × 5 + 4 × 7 = 43으로 2행 1열의 값이 된다.

7. 첫 번째 행렬의 2행과 두 번째 행렬의 2열을 곱한다.

8. 3 × 6 + 4 × 8 = 50으로 2행 2열의 값이 된다.

행렬의 곱은 새로운 행렬을 만든다.

 

행렬 곱셈의 결과

직접 계산을 해보자.

눈으로만 보면 실수할 확률이 높다.

 

행렬의 곱셈, 파이썬 넘파이 (Python, Numpy) 

이제 직접 행렬 곱셈을 코딩해 보자.

직접 코딩 연습 하라고 캡처함.

numpy를 import 해서 array를 사용해야 된다.

6번 라인을 보면 numpy 함수 dot을 사용하고 있다. (np.dot())

행렬곱을 계산해 주는 기능은 dot 함수로 할 수 있다.

행렬곱을 할 경우 주의할 점이 있다.

모든 행렬을 곱할 수 없다. 조건이 있다.

첫 번째 행렬의 열과 두 번째 행렬의 행은 같은 숫자여야 한다.

× 2 행렬 곱하기 × 2 행렬인 경우 앞의 열 2와 뒤의 행 2가 같다.

만약 × 3 행렬 곱하기 3 × 4 행렬인 경우도 앞의 열 3과 뒤의 행 3이 같다.

× 2 행렬 곱하기 3 × 2 행렬인 경우 앞의 열 2와 뒤의 행 3이 다르다. 계산할 수 없다.

하나가 1차원 배열인 경우,

× 2 행렬 곱하기 2 배열은 첫 번째 2열과 두 번째 2가 같기에 가능하다.

2 배열 곱하기 3 × 2 행렬은 첫번째가 2이고 두 번째 행렬의 행은 3이라 다르다. 계산할 수 없다.

파이썬 코드로 확인해 보자.

딥러닝 신경망 다차원 배열 (행렬)

결과는 다음과 같다.

6번 라인은 A1의 행렬로  (4, 3)

7번 라인은 A2의 행렬로 (3, 2)

A1의 열과 A2의 행이 3으로 같다. 그래서 오류 없이 결과가 나온다.

딥러닝 신경망 다차원 배열 (행렬)

4번 라인을 보면 × 2 행렬이다.

6번과 7번 라인을 보면 (4, 3) (2, 2)가 되고 첫번째 열은 3 두 번째 행은 2 다르다.

위 코드를 실행하면 오류가 난다.

앞의 열과 뒤의 행 숫자가 맞지 않아 계산 불가 오류가 남.

× 2 행렬 곱하기 2 배열도 코딩해 보자.

(2,2) × (2)

첫 번째 열 2와 두 번째 1차원 2 배열과 일치한다. 

잘 실행된다.

(2) × (2,3)

이 예제는 1차원 배열과 2차원 행렬의 곱이다. 

첫 번째 1차원 2와 두 번째 2차원 행인 2와 일치해서 잘 된다.

다차원 배열, 행렬과 신경망과의 관계

이전 포스팅에서 신경망의 구조와 퍼셉트론에 대해 알아봤다.

2025.03.21 - [인공지능(AI)/딥러닝(DeepLearning)] - [딥러닝]신경망과 활성화 함수(계단 함수, 시그모이드 함수, ReLU 함수) 계산 방법. 초보용 핵심 정리.

 

[딥러닝]신경망과 활성화 함수(계단 함수, 시그모이드 함수, ReLU 함수) 계산 방법. 초보용 핵심 정

딥러닝을 공부하면서 이해하기 어려운 부분이 나온다. 나를 위해 정리해 봤다. 같은 공부를 하는 독자가 있다면 조금이나마 도움이 되길 바란다.시작해 보자. 신경망이란?신경망(Neural Network)은

tiboy.tistory.com

신경망은 입력층, 은닉층 그리고 출력층으로 구성되어 있다.

퍼셉트론을 보면 가중치(w)와 편향( 𝞱)을 활용해 계산 후 출력값을 만든다.

여기서, 다차원 배열(행렬)이 신경망에서 어떻게 활용되는지 궁금해진다.

먼저 신경망과 퍼셉트론의 예를 보자.

딥러닝 신경망 다차원 배열 (행렬)

입력층, 은닉층, 출력층이 있는 신경망 구조의 예다.

입력값은 x1, x2로 1차원 배열로 보자. 

입력층이 가중치(w)와 곱하고 편향을 더하면 은닉층의 a1, a2 값이 나온다.

이 식을 행렬의 곱으로 계산하면 된다.

처음 1차식 2 배열과 가중치 2차식 × 2 행렬을 곱한 뒤 편향 b를 더한다는 의미다.

이렇게 그림으로 그리면 입력층 x가 1, 2로 2개이고 가중치 시작 밑이 1과 2만 있어 2개라 계산이 가능하다는 의미다.

만약 가중치 밑 3이 존재한다면 구조 자체가 잘못된 것이라는 의미다.

은닉층 a 가 3개라도 가중치 시작 밑은 1과 2면 된다.

그림으로 간단하게 보자.

?를 잘 살펴보자

x1의 선은 빨간색이다. x1에서 출발했게이 w밑이 1로 시작하고 a1로 도착하면 w밑이 1로 끝난다. w11   

x2의 선은 파란색이다. 만약 a2로 간다면 x2에서 시작, a2로 도착이기에 w22가 된다.

x3가 없는데 x3에서 출발 a1에 도착하는 가중치 w31을 초록색으로 표현했다.

?를 보면 x3 이 없다. 그래서 행렬 곱이 불가능하다는 의미다.

 

신경망, 활성화 함수 그리고 행렬곱

다차원 배열(행렬) 곱을 파이썬 넘파이(Python Numpy)로 코드를 작성해 보자.

실제와 유사하게 활성화 함수도 추가했다.

지금까지 공부한 부분을 복습하고 확인하는 과정이라 생각하자.

시작~

import numpy as np

# 활성화 함수 시그모이드
def sigmoid(x):
 return 1 / (1 + np.exp(-x))

# 입력값 x 2개 설정
x = np.array([1.0, 2.0])

# 가중치 w
w = np.array([[0.1, 0.4], [0.2, 0.5]])

# 편향 b
b = np.array([0.1, 0.2])

# 계산해보자.
# 입력값 x와 가중치 w로  dot 함수로 행렬곱 계산 더하기 편향.
a = np.dot(x, w) + b

# 활성화 함수에 a 적용
z = sigmoid(a)

# 결과 출력
print(z)

# 결과 [0.64565631 0.83201839]

직접 코딩해 보자.

위 코드를 직접 복사해서 사용해도 된다. 마지막 라인에 결과도 추가했다.

친절하게 주석도 달았으니 자세히 살펴보면 이해될 것이다.

안되면 댓글에~

지금까지 딥러닝 신경망에서 중요한 역할을 하는 다차원 배열(행렬)의 곱셈에 대해 알아봤다.

이제 우리는 딥러닝 신경망에서 다차원 배열(행렬) 곱셈을 활용할 수 있게 되었다.

열공 열코딩~

반응형