퐈니썬's LIfe - 잘 실패하자 RSS 태그 관리 글쓰기 방명록
Python (8)
2025-04-11 15:54:25
728x90
반응형

Python으로 작성된 스크립트를 Windows 환경에서 .exe 파일로 변환하여 다른 사용자에게 쉽게 배포할 수 있도록 하는 방법을 설명합니다.


준비물

다음 프로그램과 파일이 준비되어 있어야 합니다.

  • 파이썬(Python) 설치된 환경 (다운로드 페이지)
  • 배포하고자 하는 Python 스크립트 파일 (.py)
  • PyInstaller (파이썬을 EXE로 변환해주는 패키지)

1. PyInstaller 설치

먼저, PyInstaller라는 프로그램을 설치합니다.

1. 키보드에서 Windows + R을 누르고, cmd를 입력 후 엔터를 누르면 명령 프롬프트가 실행됩니다.

2. 명령 프롬프트에 아래 명령어를 입력한 뒤, 엔터를 누릅니다.

pip install pyinstaller
  • 설치가 완료되면 다음과 같이 메시지가 표시됩니다.
Successfully installed pyinstaller-5.x.x

2. EXE로 변환하기

PyInstaller를 사용하여 Python 스크립트를 EXE 파일로 변환하는 과정입니다.

1. 배포할 Python 스크립트 파일이 있는 폴더로 이동합니다.
예를 들어, 파일 위치가 다음과 같다면:

C:\Users\홍길동\Documents\my_script.py

명령 프롬프트에서 다음 명령어를 입력합니다.

cd C:\Users\홍길동\Documents
  • 해당 폴더 위치로 이동된 것을 확인합니다.

2. PyInstaller 명령어로 EXE파일을 생성합니다.

pyinstaller --onefile my_script.py

옵션 의미

--onefile 스크립트를 하나의 exe 파일로 만들어줍니다.
--noconsole (선택사항) 실행 시 검은색 콘솔 창을 표시하지 않습니다 (GUI 프로그램일 경우 권장).

GUI 프로그램인 경우는 아래처럼 하세요:

pyinstaller --onefile --noconsole my_script.py
  • 명령어를 실행하면 자동으로 EXE 생성 과정이 진행됩니다. 몇 분 정도 걸릴 수 있습니다.
  • 정상적으로 진행되면 아래 메시지가 출력됩니다.
Building EXE from EXE-00.toc completed successfully.

3. EXE 파일 확인하기

위 과정을 모두 마치면 아래 폴더가 생성됩니다:

  • dist 폴더 : EXE 파일이 저장된 곳
  • build 폴더 : 생성 중인 중간 파일이 있는 폴더 (삭제 가능)
  • .spec 파일 : 생성된 설정파일 (삭제 가능)

최종적으로 생성된 EXE 파일은 다음 위치에 있습니다.

C:\Users\홍길동\Documents\dist\my_script.exe

이 my_script.exe 파일을 복사하여 다른 PC에서도 바로 실행할 수 있습니다.


4. EXE 파일 실행하기

EXE 파일을 실행하는 방법은 간단합니다.

  • 만들어진 my_script.exe를 더블 클릭하면 바로 실행됩니다.
  • 파일은 독립적으로 실행되기 때문에, Python을 따로 설치하지 않은 환경에서도 사용 가능합니다.

자주 발생하는 문제 해결법

실행이 안 되거나 오류가 발생할 때

  • 스크립트에서 파일 경로를 절대 경로로 쓰면 문제가 발생할 수 있습니다. 항상 상대 경로를 사용하거나, 파일 경로를 조정하세요.
  • 외부 라이브러리를 사용하는 경우 명시적으로 포함해야 할 수 있습니다.
  • pyinstaller --onefile --hidden-import 라이브러리이름 my_script.py

예시:

pyinstaller --onefile --hidden-import pandas my_script.py
  • 생성된 폴더 (dist 폴더)는 다른 위치로 이동해도 문제없이 실행 가능합니다.
    하지만 EXE 파일 하나만 가져가는 것이 아니라, 생성된 모든 파일(폴더 포함)을 옮겨야 문제가 없습니다.

정리 및 요약

단계 명령어 요약

PyInstaller 설치 pip install pyinstaller
EXE 생성 pyinstaller --onefile 스크립트.py
GUI 프로그램 생성 pyinstaller --onefile --noconsole 스크립트.py
외부 라이브러리 추가 포함 pyinstaller --onefile --hidden-import 라이브러리이름 스크립트.py

 

728x90
반응형

'Programming > Python' 카테고리의 다른 글

파이썬 *arg 와 **kwargs 이해 하기  (0) 2022.03.11
파이썬 f-string  (0) 2021.12.31
파이썬 모듈이란? 패키지란?  (0) 2021.07.01
파이썬 PEP8 스타일 가이드 정리  (0) 2021.07.01
파이썬 클래스 상속  (0) 2021.06.28
2022-02-15 00:10:52
728x90
반응형

<Introduction>

본 포스트에서느 이미지 처리 중 "밝기조절" 과 "대조도"에 대해 알아보고 구현해보고자 합니다.


<Luminosity>

명도라고도 불리는 밝기는 이미지의 픽셀 값에 사용자가 설정하여 입력할 밝기도를 정하여 픽셀값에 더해주면 됩니다. 

 

픽셀의 값이 증가하면, 이미지가 밝아집니다. 반면에 픽셀의 값이 감소하면 어둬어집니다.

 

$$ LuminosityImageValue = ImageValue + LuminosityValue $$

 

간단하게 이미지의 픽셀을 불러와서 명도 수치를 더해주면 됩니다!

 

<Luminosity - 구현>

from PIL import Image, ImageDraw

# 설정하고자 하는 밝기도
luminosity = 80

# 이미지 로드
input_image = Image.open("input.png")
input_pixels = input_image.load()

# 출력 이미지 생성
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)

# 이미지의 픽셀에 밝기도 더하여 출력
for x in range(output_image.width):
    for y in range(output_image.height):
        r, g, b = input_pixels[x, y]
        r = int(r + luminosity)
        g = int(g + luminosity)
        b = int(b + luminosity)
        draw.point((x, y), (r, g, b))

output_image.save("output.png")


<Contrast 대조도>

Contrast는 이미지의 밝은 부분과 어두운 부분의 차이를 의미하고, 이를 조절한다는 것은 이미지의 밝은 부분과 어두운부분의 차이를 조절한다는 의미입니다. 이는 이미지내의 물체를 선명하게 보는 효과를 가지고 옵니다. 

 

예를들어, 이미지 안의 픽셀들이 대부분은 비슷한 Intensity(값)을 가진다면 어떨까요?

 

이미지는 아래와 같이 어떠한 물체 정보도 얻기 힘들 것입니다. 

 

 

이 경우를 대조도가 낮다 라고 말할 수 있습니다. 반면에, 대조도가 높다는 것은 이미지 내의 물체를 식별하는데 용이하고 이는 선명하다 라는 느낌을 주게됩니다. 

 

<Contrast 대조도 - 구현>

앞서 말씀드린 것처럼 대조도가 높다는 것은 이미지 내의 물체를 식별하는데 용이하고, 선명하다 라는 느낌을 주게됩니다. 즉, 대개는 대조도를 높여 이미지를 선명하게 하는 것이 이미지의 질을 높이는 방향일 것입니다. 

 

어떻게 대조도를 만드느냐에 대해는 여러가지 방법론이 있습니다. 하지만 핵심은 "intensity 값의 곱" 입니다.

 

즉, 입력이미지의 픽셀에 어떠한 조정 값을 곱하여 대조도를 변경 할 수 있습니다. 

 

예를 들어,  A라는 픽셀은 100이라는 Intensity를 가지고, B라는 픽셀은 50이라는  intenstiy를 가진다고 가정합니다.

 

Contrast를 높이기 위해 두 픽셀 값에 대해 1.5를 곱한다고 하면, A= 150, B=75가 됩니다.

 

1.5를 곱하기 전의 A-B의 값은 50이였지만, 1.5를 곱한 후의 A-B의 값은 75입니다.

 

즉, 두 픽셀의 값의 차이가 더 벌어진 것입니다. 이러한 원리로 대조도를 조정합니다.

 

이때 곱해지는 값을 정하는 방법은 여러가지가 있습니다.

 

from PIL import Image, ImageDraw

# Load image:
input_image = Image.open("input.png")
input_pixels = input_image.load()

# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)

# Find minimum and maximum luminosity
imin = 255
imax = 0
for x in range(input_image.width):
    for y in range(input_image.height):
        r, g, b = input_pixels[x, y]
        i = (r + g + b) / 3
        imin = min(imin, i)
        imax = max(imax, i)

# Generate image
for x in range(output_image.width):
    for y in range(output_image.height):
        r, g, b = input_pixels[x, y]
        # Current luminosity
        i = (r + g + b) / 3
        # New luminosity
        ip = 255 * (i - imin) / (imax - imin)
        r = int(r * ip / i)
        g = int(g * ip / i)
        b = int(b * ip / i)
        draw.point((x, y), (r, g, b))

output_image.save("output.png")

 

 

728x90
반응형
2021-07-16 14:30:04
728x90
반응형

00. 서문

오토 인코더에 대해서 공부해야 할 일이 생겨서, 하는 도중 정리하기 위해 포스팅을 하게 되었습니다.

공부하여 작성하는 거라, 부족할 수 있으니 많은 피드백 주시면 감사하겠습니다.

01. 오토 인코더 (autoencoder)

오토 인코더는 비지도 학습 방법의 하나입니다. 그러기 때문에 모델을 학습하기 위한 명확한 라벨(정답)이 제공되지 않습니다. 즉, 오토 인코더를 학습하기 위해서는 입력 데이터를 필요로 합니다.

 

 제가 공부하면서 느낀 것은 오토 인코더의 학습과정은 마치 "압축과 압축해제"와 같다고 느꼈습니다.

이미지를 학습한다고 가정했을 때, 입력 이미지를 받고, 학습 레이어를 거쳐 입력 이미지를 잘 설명할 수 있는 축소된 차원이 데이터("latent space" 또는 "bottle neck"이라고 하는)로 변환되고, 이 데이터를 다시 reconstruct하여 입력이미지를 복원하거나 target 이미지를 구성해내는 과정을 거친다고 이해했습니다.

 

 

 

조금 더 깊게 생각했을 때, 입력층에서 이미지가 들어오고, 각 노드들은 이에 대한 특징(feature)을 Encoder를 통해 차원 축소를 거치고, 입력 및 target 이미지를 잘 설명할 수 있는 데이터로 압축한 후에 이를 Decoder를 통해 복원하여 표현하는 과정이라고 이해했습니다. 

마치 오토 인코더는 PCA와 비슷하다고 생각도 들었습니다. 하지만, PCA는 선형적 차원축소하는 반면 오토인코더는 비선형적 차원축소를 한다고 합니다 (활성함수 이야기 인거 같습니다).

 

02. Encoder와 Decoder

오토인코더 과정은 3단계로 나누어 볼 수 있을 거 같습니다. 

  • 데이터 입력
  • Encoder 
  • Decoder

Encoder: Encoder는 결국 입력 데이터를"입력 데이터의 특징을 잘 설명할 수 있는 데이터로 차원 축소한다" 이 공간을 "latent-space", 또는 "bottle neck"이라고 합니다. 

 

Decoder: Decoder는 입력 및 target 데이터로 복원(복호화)을 합니다. decoder가 encoder로부터 받은 데이터로 정확하게 입력 및 target 데이터로 복원한다면 decoder의 성능이 좋다고 표현합니다.

728x90
반응형
2021-06-28 11:10:56
728x90
반응형

01. 파이썬 클래스 (Class)란?

클래스는 어떤 것이고 왜 필요할까?

01.1. 클래스의 개요

  • 클래스는 객체의 구조와 행동을 정의한다.
  • 객체의 클래스는 초기화를 통해 제어한다.
  • 클래스는 복잡한 문제를 다루기 쉽게 한다.

 

💡메모

객체란, 어떠한 속성의 값, 행동을 가지는 데이터를 일컫습니다. 파이썬에서 숫자, 문자, 함수 등등 모든 데이터들은 여러 속성과 행동을 가지고 있고 각각이 객체라 볼 수 있습니다.

예시)

세탁기라는 객체는 "빨래를 한다", "빨래 정지한다", "가로 100cm" 등의 속성과 행동으로 표현할 수 있습니다. 이렇든 정의된 데이터가 속성과 행동을 가진다면 객체라고 말할 수 있겠네요!

 

클래스는 위와 같은 특성을 가지는데요, 왜 그러한지에 대해 차근차근 보겠습니다.

 

02. 클래스는 복잡한 문제를 다루기 쉽게 한다?

아래의 예시를 통해 이를 확인 할 수 있습니다.

클래스를 통해 복잡하게 반복해야하는 행동을 쉽게 정의하여 해결 할 수 있습니다.

 

곱셈 계산 기능을 가지는 계산 프로그램 multiply가 있습니다.

이 계산 프로그램은 현재 까지 입력된 모든 숫자들의 곱을 구해야합니다.

예시)

result = 1

def multiply(num):
    global result
    result *= num
    return result

print(multiply(3))
print(multiply(4))
print(multiply(6))

[out]
3
12
72

 

그런데, 어떠한 상황에서 multiply의 기능을 하는 계산 프로그램이 두개가 필요하다고 생각해봅시다.

예를들어, 1 x 4 x 10 라는 연산과 20 x 4 라는 연산을 한번에 진행해야 할 때, 이러한 상황을 고려해보면 위 와같은 multiply 프로그램을 multiply_1, multiply_2와 같이 두개를 만들어야 합니다.

 

예시)

result_1 = 1
result_2 = 1

def multiply_1(num):
    global result_1
    result_1 *= num
    return result_1

def multiply_2(num):
    global result_2
    result_2 *= num
    return result_2

print(multiply_1(1))
print(multiply_1(4))
print(multiply_1(10))

print(multiply_2(20))
print(multiply_2(4))

[out]
1
4
40
20
80

 

좋습니다. 2개까지는 충분히 만들 수 있을거 같습니다. 하지만, 5개, 20개 혹은 그이상이 필요할 때는 어떻게 해야할까요, 하나하나 직접 구현 하는 것은 굉장히 복잡하고, 비효율적입니다.

여기서! 클래스는 이러한 상황을 매우 간단하게 해결합니다!

 

예시)

#Multiply 클래스 생성
class Multiply:
    def __init__(self):
        self.result = 1
    
    def multiply(self, num):
        self.result *= num
        return self.result

# 클래스를 통한 계산기 1 
multiply_1 = Multiply()
print("계산기 1 결과")
print(multiply_1.multiply(2))
print(multiply_1.multiply(5))

# 클래스를 통한 계산기 2
multiply_2 = Multiply()
print("계산기 2 결과")
print(multiply_2.multiply(10))
print(multiply_2.multiply(9))

 

위와 같이 Multiply라는 클래스를 생성하여, multiply_1, multiply_2의 인스턴스를 형성하여 사용할 수 있습니다!

많이 비유되는 거처럼, 클래스는 마치 틀, 공장과 같은 역할을 해서 자신의 형태 결과물인 인스턴스를 만들어냅니다!

 

3. 객체의 클래스는 초기화를 통해 제어?

클래스를 생성하고 생성된 클래스를 인스턴스로 형성하여 반복적으로 기능을 할 수 있는 것이 클래스의 특징인데요, 여기서 항상 들어가는 "__init__()" 이라는 함수가 있습니다.

이는 생성자라하며, 인스턴스가 생성될때 항상 실행되는 것입니다.

즉, 위의 Multiply라는 클래스를 통해, Multiply_1, Multiply_2 라는 두개의 인스턴스가 생성되었는데요, 생성할때마다 __init__() 함수가 실행되면서 모두 self.result = 1이라는 문장을 실행합니다.

 

즉, result라는 변수를 인스턴스 형성때마다 초기화가 됩니다. 이러한 장점은 많은 변수를 추가할 필요없게 합니다.

 

💡메모

클래스에는 생성자와 소멸자라는 개념이 있습니다.

생성자는 위에서 설명한 "__init__()"에 해당되며, 이 생성자를 통해서 객체가 생성될때 어떤 변수의 값을 세팅하는 등 여러가지 작업을 할 수 있습니다.

반면에, "__del__()" 라는 소멸자는 리소스 해제등의 종료 작업을 하기위해 사용됩니다.

 

#Multiply 클래스 생성
class Multiply:
    def __init__(self):
        self.result = 1
    
    def multiply(self, num):
        self.result *= num
        return self.result

#클래스가 인스턴스로 형성될 때마다 __init__() 함수는 실행된다. 
#즉 result 인스턴스 형성 마다 개별적으로 초기화

4. 클래스는 객체의 구조와 행동을 정의?

이 특징은 위를 잘 읽으셨다면 충분히 이해 하실 겁니다.

즉, 어떠한 객체에 대해 복잡한 구조를 만들 필요 없이 클래스를 통해서 객체에 대한 행동과 속성을 구조화 시켜 간단하게 해결 할 수 있습니다!!

 

 

728x90
반응형
2021-06-25 15:31:11
728x90
반응형

01. 서문

최근에 DICOM 이미지를 축대칭을 하는 과정에서 numpy의 flip 메소드를 편하게 사용하여 작성합니다. 물론, 일반 이미지의 경우, cv2의 flip기능을 사용해도 편합니다.

다만, DICOM 의 array만 받아서 처리할때 배열을 다루는 numpy 함수를 사용했던 것을 메모차 작성합니다.

도움이 된다면 좋겠습니다.

02. 이미지 축 대칭

대칭에는 여러가지가 있지만, 본 포스트에서는 "반사대칭" 즉, 차원에 대한 대칭에 대해 다루었습니다.

2 차원에는 대칭축 (일명 대칭 선)이 있고 3 차원에는 대칭 평면이 있습니다.

모든 점에 대해 공통 평면의 반대편에서 등거리에있는 다른 점과 일대일 매핑이있는 객체 또는 그림을 대칭 대칭이라고합니다.

03. numpy flip

numpy의 문서를 보면 numpy flip은 다음과 같이 설명되어 있습니다.

 

flip 메소드는 배열의 원소들의 순서를 재배치 해주는 역할인것이고, 배열(array)을 입력으로 출력 또한 배열형태 이고, axis라는 옵션에 따라서 차원이 정해집니다.

예시.

>>> A = np.arange(10).reshape(2,5)
>>> print(A)
[[0 1 2 3 4]
 [5 6 7 8 9]]

>>>print(np.flip(A,0))
[[5 6 7 8 9]
 [0 1 2 3 4]]

>>>print(np.flip(A,1))
[[4 3 2 1 0]
 [9 8 7 6 5]]

위 와 같이 axis가 0, 1에 따라 위와 아래가 바뀌던지 원소들의 배열이 바뀐다던지 등의 차원 반전이 생깁니다. axis는 차원에 따라 최대 숫자가 늘어납니다.

 

04. numpy flip을 활용한 이미지 축 대칭 시키기

이를 통해서 이미지를 반전시키는 것이 가능한데요, 최근에 DICOM 이미지를 통해 변환한 경험으로, 오픈 DICOM 데이터인 "Digimouse"를 사용해보았습니다.

주로 사용하시는 DICOM형태는 아니고, nifty 파일 형식으로 되어 있는 이미지 파일이지만, DICOM 또한 pydicom으로 array를 출력하면 동일하게 적용됩니다. 

 

DICOM 오픈이미지; Digimouse

https://neuroimage.usc.edu/neuro/Digimouse_Download

 

Digimouse_Download - Biomedical Imaging Group"

Digimouse_Download (2012-02-12 07:26:42에 cpe-76-170-79-250가(이) 마지막으로 수정)

neuroimage.usc.edu

여기서 Atlas 데이터를 변형 해보았습니다.

4.1 R-L 대칭

좌: 원본

우: 변환본

4.2 A-P 대칭

좌: 원본

우: 변환본

4.3 I-S 대칭

좌: 원본

우: 변환본

위 와 같이 axis가 0, 1에 따라 위와 아래가 바뀌던지 원소들의 배열이 바뀐다던지 등의 차원 반전이 생깁니다. axis는 차원에 따라 최대 숫자가 늘어납니다.

5. 작성코드

import nibabel as nib
import numpy as np
# ctfn = '/home/hwan/code/study/04.DICOM/nibabel/ct_380x992x208.nii'
niifn = '/home/hwan/code/study/04.DICOM/nibabel/nii/atlas_380x992x208.nii'


proxy = nib.load(niifn)
data = proxy.get_fdata()
array = data.view(type=np.ndarray)
# np.flip(array,0) -> 좌우대칭 RL
# np.flip(array,1) -> 앞뒤대칭 AP 
# np.flip(array,2) -> 상하대칭 IS
array_flip = np.flip(array,2)
aff = proxy.affine
hdr = proxy.header

zflip = nib.Nifti1Image(array_flip,aff, hdr)
nib.save(zflip, './ISflip_atlas_380x992x208.nii')
728x90
반응형

'Programming > Python' 카테고리의 다른 글

파이썬 *arg 와 **kwargs 이해 하기  (0) 2022.03.11
파이썬 f-string  (0) 2021.12.31
파이썬 모듈이란? 패키지란?  (0) 2021.07.01
파이썬 PEP8 스타일 가이드 정리  (0) 2021.07.01
파이썬 클래스 상속  (0) 2021.06.28
2021-03-04 19:32:22
728x90
반응형

#1. Andrew Ng. Lecture.C1W2L04

강의 출처 : www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w

 

DeepLearningAI

Welcome to the official DeepLearning.AI YouTube channel! Here you can find the videos from our Coursera programs on machine learning as well as recorded events. DeepLearning.AI was founded in 2017 by machine learning and education pioneer Andrew Ng to fill

www.youtube.com

본업 이외에 따로 무엇가를 준비한다는 것은 쉬운일은 아닌거 같다. 하지만, 꾸준히 하자!

01. Lecture 10. Gradient Descent

  • 강의 목적 - "경사 하강법 (Gradient Descent)" 알고리즘을 사용한, 매개변서 w, b를 훈련세트에 학습시키는 방법.
  • 이전 강의의 연장선으로, 로지스틱회귀 함수의 경사하강법에 대한 설명.

그림 1

로지스틱 회귀법의 "시그모이드 함수" 를 예로 들어 설명합니다.

 

(그림 1의 첫번째 식) "시그모이드 함수"의 표현 식입니다.

 

(그림 1의 두번째 식)  "비용함수"를 J라 할 때, 비용함수 J는 w, b에 대한 함수가 됩니다.

 

이 함수 J는  "손실함수의 평균"으로 정의합니다. 즉, 손실함수와 비용함수는 목적은 같지만 약간의 의미는 다릅니다.

 

결국, m개의 데이터셋이 있다면 각 데이터셋의 손실함수를 계산한 값의 평균이 "비용함수" 로 정의됩니다.

 

이는 훈련셋이 얼마나 참값과 예측값이 맞는지에 대한 측정이 가능하죠.

 

(그림 1의 그래프) 두 가로축은 w,b에 대한 정의가 된 축입니다. 세로축은 비용함수 J에 의한 (w,b)의 출력 값이 되겠죠.

 

J함수가 저 그림에 따른 모양이라면, 어느한점 (w,b)에서 가장 적은 최소값을 찾으려 할 것입니다.

 

그것이 알고리즘이고, 비용함수 J가 아래로 볼록한(convex)한 모양이라는 것이 로지스틱 회귀가 적용에 적절한 비용

 

수가 된다는 것을 의미하고, 이대의 w, b가 적절한 파라미터라고 할 수 있겠습니다.

 

그림 2

결국에는 비용함수 J의 목적은 최소 값을 찾는 것이고, 이 최소값을 찾아나가는 방법이 "경사하강법"입니다.

 

그리고, 비용함수 J가 최소 값일 때 w, b가 적절한 파라미터이므로 이 w, b를 갱신해가며 비용함수 J를 따라 함수값

 

이 최소 값이 되는 w, b를 찾아야겠죠.

 

그림2가 이에 대한 내용입니다. 

 

경사하강법을 본다면 결국 w를 갱신해나가는 것이고, 이 갱신은 기존 w에서 J(w)의 기울기 값에서 a(학습률)의 곱

 

을 빼 는 것으로 갱신해나간다고 합니다. 

 

즉, 기울기가 양일때는 w가 작아지는, 기울기가 음일때는 w가 커지면서 J(w)가 작은 global 미니마를 찾는것이죠. 

 

여기서 중요한 것은 우리가 w,b를 경사하강법으로 J(w,b)가 최소가 되는 w,b를 찾는 것이다.

 

어떻게?? 미분으로!!

 

그림 2의 모든 식들이 해당 내용 w := w - a* dJ(w,b)/dw b := b - a* dJ(w,b)/db  - 우리는 천천히 이해할 수 있습니다!

 

다음에는 미분으로 어떻게 찾아가는지 공부하면서 미분의 의미도 정립해보도록 하겠습니다.

728x90
반응형
2021-03-03 13:17:38
728x90
반응형

01. Keras

01. Keras란?

케라스는 딥러닝 모델을 간편하게 만들고, 훈련시킬 수 있는 파이썬을 위한 딥러닝 프레임워크로, 백엔드 엔진에서 제공하는 최적화된 텐서 라이브러리를 사용합니다.

케라스는 모듈 구조로 구성되어 있어 하나의 텐서 라이브러리에 국한하여 구현되어 있지 않고, 여러 가지 백엔드 엔진과 매끄럽게 연동됩니다.

현재는 TensorFlow, Theano, CNTK 3개를 백엔드 엔진으로 사용할 수 있습니다. (백엔드 엔진 변경하는 방법; https://keras.io/api/utils/backend_utils/)

 

02. Keras workflow

케라스를 사용하는 대부분의 작업 흐름은 다음과 같습니다.

  1. 입력 텐서와 타겟 텐서로 이루어진 훈련 데이터를 정의
  1. 입력과 타겟을 맵핑하는 층으로 이루어진 네트워크(모델)를 정의
  1. 손실함수, 옵티마이저, 모니터링하기 위한 측정지표를 선택하여 학습
  1. 훈련 데이터에 대해 모델의 fit() 메서드를 반복적으로 호출

 

02. Keras를 이용하여 MNIST 학습하기

01. 데이터 호출

가장 기본적인 예제인 MNIST 데이터셋을 이용하여 손글씨 데이터를 분류 예측하는 모델 제작.

케라스에서 MNIST 데이터셋을 numpy배열 형태로 호출이 가능하다.

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
# 노말라이즈를 하는, 0~1의 이미지를 기준으로 한다. (왜그런지 보쟈)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

02. 훈련, 테스트 데이터 설정

 

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels) #범주형이라고하고, 원핫인코딩 필수적인 작업
#원핫 인코딩 왜하냐 알아보기.
test_labels = to_categorical(test_labels)

03. 모델 정의

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,))) 512개의 perceptron

model.add(layers.Dense(10, activation='softmax'))
model.add(layers.Dense(len(train_labels[0]), activation='softmax'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

04. 모델 훈련

# fit() 메서드로 모델 훈련 시키기
model.fit(train_images, train_labels, epochs=5, batch_size=128)

05. 정확도 측정

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('test_acc: ', test_acc)

06. 결과 보기

Epoch 1/5
469/469 [==============================] - 1s 2ms/step - loss: 0.4283 - accuracy: 0.8745
Epoch 2/5
469/469 [==============================] - 1s 2ms/step - loss: 0.1105 - accuracy: 0.9669
Epoch 3/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0683 - accuracy: 0.9800
Epoch 4/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0469 - accuracy: 0.9867
Epoch 5/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0355 - accuracy: 0.9891
313/313 [==============================] - 0s 576us/step - loss: 0.0662 - accuracy: 0.9811
test_acc:  0.9811000227928162

03. 코드내용 학습하기

01. MNIST 데이터 셋에 대하여

01. MNIST 데이터 셋?

National Institute of Standards and Technology의 줄임말로, 미국 국립표준기술연구소의 손으로 쓴 글자 데이터셋에서 숫자만 따로 뽑아낸 데이터 셋.

0~255사이의 값을 가지는 흑백 이미지이며 28x28(784) 사이즈를 지니며 7만 개의 이미지(6만 개 트레이닝 셋, 1만 개 테스트 셋)으로 구성되어있다.

02. MNIST 데이터 셋 살펴보기

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

------------------------------------------------------------------------------
test_image : shape : (10000,28,28) 28x28 이미지 10000장
test_label : shape : 10000 10000장 이미지 대한 0~9까지의 라벨
train_image : shape : (60000,28,28) 28x28 이미지 60000장
train_label : shape : 60000 60000장 이미지 대한 0~9까지의 라벨

* 각 한장에 28x28 배열이며 각 배열의 값들은 0~255의 값을 가지고 이미지로 보았을때 
0~9까지의 형상을 가진다

03. MNIST 데이터 셋 PLOT 해보기

import matplotlib.pyplot as plt
#train image의 5번째 이미지 추출
image = train_images[4]  #reshape전의 이미지

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])
#실행결과 Console: train_image 4번째 라벨은 9 

04. 모델구조 파악하기

모델을 정의하는 방법은 두 가지로, Sequential 클래스함수형 API를 사용한다.

1) Sequential 클래스 : 가장 자주 사용하는 구조로, 층을 순서대로 쌓아 올린 네트워크

2) 함수형 API : 완전히 임의의 구조를 만들 수 있는 비순환 유향 그래프(DAG) 만듬 ( 공부가 필요)

 

해당 코드에서는, Sequential 클래스 형태로 모델화하였다.

모델은 2개의 Dense 층으로 되어있고, 각각 "relu", "softmax"의 활성함수를 가진다.

마지막 층은 10개의 확률 점수가 들어 있는 배열을 반환하는 소프트맥스층이며, 각 점수는 현재 숫자 이미지가 10개의 숫자 클래스 중 하나에 속할 확률을 나타낸다(?)

#model.summary() 통해 전체적인 구조
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

05. 결과 파악하기

학습된 모델이 Test 모델을 판별할때, 98.34%로 MNIST의 숫자를 맞춘다는 의미이다.

즉, 테스트 데이터 10000개 중에서 200장 가량 틀렸다는 것으로 볼 수 있다.

Test loss: 0.08414454758167267
Test accuracy: 0.9817000031471252

 

 

예측 라벨과 실제 테스트라벨이 다른 결과들 16개를 랜덤하게 선정하여 보았을때, 실제로 사람이 보아도 판별하기 쉽이낳는 것들이 있는 것을 확인 할 수 있다.

04. 전체코드

01. 학습하기

 

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical
import matplotlib.pyplot as plt
from keras.utils import plot_model

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
model.add(layers.Dense(10, activation='softmax'))
model.summary()

# 구 조확인
from IPython.display import SVG
from keras.utils import model_to_dot

# SVG(model_to_dot(model, show_shapes=True).create(prog='dot',format='svg'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

# fit() 메서드로 모델 훈련 시키기
history=model.fit(train_images, train_labels,epochs=10, batch_size=64, verbose=1)
# batch size가 높을수록, 속도빠르고, 정화도가 낮아.

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=0)

print('Test loss:', test_loss)
print('Test accuracy:', test_acc)
# 학습 정확성 값과 검증 정확성 값을 플롯팅 합니다.

#결과파악.

import random
import numpy as np
predicted_result = model.predict(test_images)
predicted_labels = np.argmax(predicted_result, axis=1)

test_label = np.argmax(test_labels, axis=1)

wrong_result = []

for n in range(0, len(test_label)):
    if predicted_labels[n] != test_label[n]:
        wrong_result.append(n)

samples = random.choices(population=wrong_result, k=16)

count = 0
nrows = ncols = 4

plt.figure(figsize=(12,8))

for n in samples:
    count += 1
    plt.subplot(nrows, ncols, count)
    plt.imshow(test_images[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
    tmp = "Label:" + str(test_label[n]) + ", Prediction:" + str(predicted_labels[n])
    plt.title(tmp)

plt.tight_layout()
plt.show()

02. 결과보기

from keras.datasets import mnist

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

import matplotlib.pyplot as plt
#train image의 4번째 이미지 추출
image = train_images[4]

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])

num = 10
images = train_images[:num]
labels = train_labels[:num]

num_row = 2
num_col = 5

#plot images
fig, axes = plt.subplots(num_row, num_col, figsize=(1.5*num_col, 2*num_row))
for i in range(num):
    ax = axes[i//num_col, i%num_col]
    print(i//num_col, i%num_col)
    ax.imshow(images[i], cmap='gray')
    ax.set_title('Label: {}'.format(labels[i]))
plt.tight_layout()
plt.show()
728x90
반응형
2021-02-25 18:45:20
728x90
반응형

#1. Andrew Ng. Lecture.C1W2L01 ~ C1W2L03

강의 출처 : www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w

01. Logistic Regression

  • 강의 목적 - "로지스틱 회귀가 어떤 것인가" 에 대한 간략한 전달
  • "로지스틱 회귀"는 "지도학습 문제"에서 출력 레이블 y가 0 or 1 일 경우 즉, 이진 분류에 사용되는 알고리즘

예를들어, 고양이 사진인지 아닌지 구분하는 경우라면? x라는 입력이 주어지면, y의 예측값을 출력하는 알고리즘이 필요

 

할 것 즉, x는 고양이 사진이고, y의 예측값은 고양이 사진일 확률 일것 문제는, 입력 x와 파라미터 w,b가 주어졌을

 

때, 어떻게 y의 예측값을 출력 할 수 있을까?

 

잘 안되는 방법은 w*x +b 와 같은 선형식으로 두는 것. 왜??

 

선형함수는 음수도 가질 수있기에, 이진 분류에는 좋은 방법이 아니다.

 

왜냐하면, 예측 값인 y는 확률로 항상 0<y<1 값을 가져야하기 때문!! 그렇기 때문에 0과 1로 표현이 잘 되어질 수 있는

 

활성 함수인 "시그모이드 함수" 를 주로 적용한다.

 

 

위 그림은 "시그모이드 함수" 그래프와 식을 나타낸다. 이를 보면 알 수 있듯이, z가 양의 값으로 클수록 z의 함수 값은 1

 

에, z가 음의 값으로 클수록 z의 함수 값은 0에 수렴한다.

 

그러므로 로지스틱 회귀를 구현할때, y가 1이 될 확률을 잘 예측하도록 파라미터 w,b를 학습해야 한다.

 

 

02. Lecture 09. Logistic Regression Cost Function

  • 강의 목적: 파라미터 w, b를 학습하려면, 비용함수의 정의가 필요. "로지스틱 회귀"를 학습할  수 있는 비용함수에 대해 알아보자.
  • 손실함수(loss function), 비용 함수 (cost function), 목적 함수 (objective function): 머신러닝을 통한 예측값이 실제값과 차이(오차)와 관련한 식(equation)

  • 예측값과 실제값의 오차를 최소화하려 하면 비용함수 혹은 손실함수라 함. 즉, 비용함수는 예측값의 오차를 최소화하기 위해 최적화된 식이어야 함

위 식에 대해 말해보자면, i번째 y의 예측값은 w*x(i) + b의 시그모이드이며, 이때 시그모이드 함수는 첫 번째 줄의

 

where 이후의 식으로 정의가 된다. 즉, w*x(i) + b가 i번째 z로 치환이 된다고 보면 된다.

 

1~m개의 주어진 훈련 데이터를 w, b를 찾아 학습할때, 우리가 원하는 값은 i번째 y의 예측값이 훈련 세트에 포함된 i번

 

째 y의 참값과 가까워지도록 하는 것.

 

이를 측정 할 수 있는 것이 손실함수(=오차함수=비용함수)이다. 손실함수를 L이라고 부르고, y^ = 예측값, y = 참값이

 

라 할때, 1/2(y^ - y)^2가 손실함수로 표현될 수 있으나, "로지스틱 회귀" 에서는 적절한 손실함수가 아니다.

 

여기서 명심할 것은 y의 예측값과 y 참값의 오차가 얼마나 큰지를 측정하는 것이 "손실함수"

 

  • 그렇다면, 로지스틱 회귀법에서 시그모이드 함수의 적절한 손실함수는 ??다음과 같이 표현 할 수 있다.

그 이류를 이해한대로 적어보자!

손실함수는 최소화 되어야하는 것을 전제로 한다. 

y^ 이 예측값, y가 참값이라 할때 y^는 로지스틱 회귀 함수를 따른다. 

y= 1 경우)  손실함수  L=  -log(y의 예측값)이 되고, 우리는 예측값이 1 이 되길 원하므로  손실함수는 최소가 되길 원할

 

것. 그럴려면, y의 예측값(y^)이 최대 값이 되도록 그려져야하고, y^은 로지스틱 회귀 함수를 따르기에 1에 수렴하도로

 

증가할 것이다.

반면에, y = 0 경우) 손실함수 L = -log(1-y의 예측값)이 되고, 우리는 예측값이 0 이 되길 원하므로  손실함수는 최소가

 

되길 원할 것이고, 그러므로, 1-y의 예측값이 최대 값이 되도록그려져야하고,  y^는 최소가 되도록 가야할 것이다. 

y^는 로지스틱 회귀 함수를 따르기에 0에 수렴하도록 감소할 것이다.

 

 

정말 어렵지만, 조금씩 알아가고 있는것 같아 기쁘다! 꾸준히 하자!

728x90
반응형