본문 바로가기
  • 비둘기다
  • 비둘기다
  • 비둘기다
AI/Deep learning from Scratch

[머신 러닝, 딥러닝] 파이썬 기초

by parzival56 2023. 1. 1.

<목차>

1. 리스트 2. 딕셔너리

3. 함수 4. 클래스

5. 넘파이

6. matplotlib

 

 

1. 리스트

리스트란 데이터의 배열을 의미합니다. 그러나 예를 들어 c나 자바에서는 배열과 리스트라는 것을 따로 해석했습니다. 배열은 그냥 말 그대로 숫자 혹은 문자의 배열 (문자면 문자열) 이고 리스트도 의미가 일맥상통하긴 하지만 이 둘의 가장 큰 차이점은 편의성이라고 할 수 있습니다. 

예를 들어 배열을 출력하려면 for문을 거쳐 하나씩 인덱스 수를 늘리면서 출력하거나 특정 인덱스들만 출력하려면 인덱스 번호를 일일이 언급하여야 합니다. 

그러나 리스트는 이러한 문제들을 해결해주는 기능들이 존재합니다. 파이썬에서는 앞선 두 언어와 같이 배열이라는 개념이 따로 존재하지는 않고 리스트라는 개념 하나로 퉁치는 것으로 보입니다.

 

먼저 리스트의 선언입니다. 리스트는 변수와 대괄호 []만 있으면 선언이 가능합니다.

a = [1, 2, 3, 4, 5]

이렇게 a라는 변수에 숫자들의 배열이 리스트의 형태로 저장되었습니다. 

이 리스트를 그대로 출력하려면 단순히 print(a)만 해주면 됩니다.

만약 리스트의 크기를 알고 싶다면 len(a)를 하여 알 수 있습니다. 

 

여기서 알 수 있는 점은 파이썬은 다른 언어들과 달리 꼭 출력문 안에 내가 출력할 것을 넣을 필요가 없이 그냥 쓰기만 해도 출력이 된다는 것입니다. 

풀이하자면 예를 들어 len(a)를 출력하고 싶으면 print(len(a))가 아니라 그냥 len(a)만 써도 문제가 없다는 것입니다.

인덱스도 마찬가지입니다. print(a[0])처럼 할 필요 없이 a[0]만 적어도 출력이 됩니다.

 

다음은 리스트의 기능중 하나인 슬라이싱입니다.

슬라이싱은 말 그대로 자른다는 것입니다. 무엇을 자르냐면 바로 리스트의 배열이겠죠. 그러나 이 슬라이싱은 자르는 데에만 의미를 가지는 것이 아니라 자른 부위를 마음대로 다룰 수 있다는 것입니다. 

슬라이싱에서는 ' : '기호를 사용합니다. 

a[0:2] #1,2
a[1:] # 2,3,4,5
a[:3] # 1,2,3
a[:-1] # 1,2,3,4

위에서 보시다시피 슬라이싱의 주된 형태는 ' 리스트 이름 [ 시작 : 끝 + 1 ] '로 구성됩니다. 

주의할 점은 알 수 있듯이 시작점은 그냥 쓰면 되지만 끝 점은 내가 출력하고 싶은 인덱스의 +1한 숫자를 적어줍니다.

그리고 다른 형태들도 존재하는데 앞이나 뒤의 숫자가 빠진 경우입니다. 

뒤의 숫자가 빠진 경우는 시작점부터 끝까지를 의미하고 앞의 숫자가 빠진 경우는 처음부터 끝 점 -1까지를 의미합니다. 그러나 뒤의 숫자가 음수일 때는 가장 마지막의 원소의 n번째 앞까지 출력이기 때문에 주로 인덱스가 많은 경우에 사용되기도 합니다.

 

2. 딕셔너리 

딕셔너리는 리스트처럼 값들을 저장하긴 하지만 방식이 다르다고 할 수 있습니다. 

리스트는 인덱스0부터 n까지 순서대로 저장하는 것이라면 딕셔너리는 key, value로 구성됩니다.

알고 넘어가야할 점은 value는 겹칠 수 있지만 key값은 유일무이해야 한다는 것입니다. 본인의 이름과 주민번호를 생각하면 편할 것입니다. 동명이인일 수는 있지만 주민번호까지 같을 수는 없겠죠?

 

me = {'height' : 180} # 딕셔너리 생성
me['height'] # 180

me['weight' : 70] # 원소 추가
print(me)
# {'weight' : 70, 'height' : 180}

위를 보시면 me라는 딕셔너리를 생성하면서 값을 넣는 방식과 갑자기 새로운 원소를 추가할 때의 방식의 차이가 있다는 것을 알 수 있습니다. 그리고 분명 height를 먼저 넣었지만 weight가 먼저 출력되데 이 이유는 value의 크기순으로 자동으로 바꿔주는 것으로 보이네요.

 

3. 함수

함수란 수학에서 배우다시피 특정한 기능을 수행하게 해주는 상자입니다. 덧셈에 대한 하나의 함수가 갑자기 곱셈을 할 수는 없듯이 함수는 주어진 기능만을 수행하고 함수는 존재만 하지 우리가 코드에서 활용하지 않는다면 의미를 가지지 않는 코드입니다. 잠시 후 이에 대해 알아보겠습니다. 

함수는 def 함수 이름(매개변수): 으로  선언합니다. def는 define 즉, 정의한다는 뜻입니다. 이 이름과 해당 매개변수를 가지는 것을 밑의 내용을 수행하는 역할을 하는 함수로 정의한다는 것입니다. 

매개변수란 해당 함수를 불러올 때 지녀야하는 값입니다. 매개변수의 유무는 상관없습니다. 

 

이제 아까 말씀드린 함수의 의미에 대해 좀 더 알아보도록 하겠습니다.

print('hello')
# 얘는 그냥 이것만 쳐도 hello가 출력됨

def hello():
	print('hello')
    
# 얜 아무 것도 못함. 그냥 print를 하는 기능만 하기 때문
# 함수를 작동시키려면 함수를 언급을 해야함

hello()

이렇게 함수는 작성만한다고 해서 무언가를 할 수 있는 것은 아닙니다. 우리가 수학 문제를 풀 때 f(x) = x + 1이 주어지면 우리는 이것만으로는 아무것도 할 수 없습니다. 문제에서 x가 5일 때의 함숫값을 구하라고 하면 이 함수에 5를 넣어 6이라는 값을 얻을 수 있는 것입니다. 

이도 마찬가지로 함수를 작성 후 기능을 수행하게 하려면 매개변수가 있다면 "무조건 매개변수와 함께" 적어야 합니다.

 

그럼 함수를 왜 쓰냐? 하면 위의 코드는 너무 간단해서 그 의미가 안 느껴질 수도 있지만 만약 피보나치 수열을 만들고 싶을 때 이걸 다양한 값에 적용해보고 싶은데 함수를 쓰지 않는다면 값을 바꿀 때마다 일일이 다 피보나치 코드를 써줘야겠죠.

그러나 함수를 쓰면 일일이 다 선언할 필요없이 피보나치 함수 하나만 작성하고 변수만 매개변수로 넣어 계속 써주면 되니까 10000배는 편하죠.

 

4. 클래스

클래스는 하나의 자료형입니다. 우리가 흔히 자료형이라고 부르는 int, double 같은 친구들도 모두 클래스의 일종입니다. 모두 안에 함수들을 담고 있기 때문입니다. 다만 이 함수들이 우리가 구현할 수 있는 것이라기보단 시스템적인 해독으로 봐야 하기에 그렇게 보이지 않는 경우가 많죠.

위에서 말씀드렸다시피 클래스는 안에 자체적인 함수들이 존재합니다. 쉽게 설명하자면 점점 벤다이어그램의 범주를 넓히는 것입니다. 처음에는 그냥 특정 가능을 하는 문장들을 모아 관리하는 함수, 그 다음은 비슷한 기능을 하는 함수들을 관리하는 클래스죠. 

클래스는 아시다시피 생성자라는 것이 있어야합니다. 생성자는 간단히 설명하면 이 클래스는 사용하기 위한 조건, 사용설명서 같은 개념입니다. 그리고 특이하게 파이썬에서는 __init__으로 생성자를 정의하고 self라는 키워드를 사용합니다. 

class 클래스 이름:
    def __init__(self, 인수,.....):
    	~~~
    def 함수 이름(self):
    	~~~

self는 처음 봤을 때 저도 외우려고 했는데 쉽게 설명드리면 단순히 그 클래스 안에 그 클래스의 객체를 하나 생성해 놓은 것이라고 할 수 있습니다. 우리가 만약 B라는 클래스에 A 클래스의 객체를 생성하면 A클래스의 요소들을 사용할 수 있게 됩니다. self도 마찬가지로 밑에 함수의 매개변수 자리에 self만 적었는데 그 역할을 하는데 지장이 없는 것을 봤을 때 self는 이 클래스에 들어갈 인수들을 모두 포함하는 하나의 키워드이기에 인수들을 한 번에 다룰 수 있게 해주는 편리한 친구라고 보시면 될 것 같습니다. 

 

※ 저도 처음 안 사실 중 하나인데 우리가 위처럼 클래스를 사용할 때 ' : '을 활용하는데 이는 : 이전에 들어가는 매개변수에서 서로 다른 타입을 허용하지 않는 기능을 합니다. 무슨 말이냐면 만약 제가 name이라는 인수와 age라는 인수를 같이 적었을 때 이름이 Tom이라면 밑에 class name("Tom")을 넣을 것이고 age는 또 class name(30)이라고 할 것입니다. 그러나 이게 불가능합니다. 그럼 이게 가능하게 하려면 가장 상위의? 모든 기호를 포괄할 수 있는 타입인 문자로 고쳐줘야 합니다.

"30"이라고 쓰면 문제가 없겠죠?

 

5. 넘파이

넘파이를 한 문장으로 정리하자면 편한 배열입니다. 넘파이는 일단 외부 라이브러리에 존재하기 때문에 코드에 적용하고 싶으면 import로 들여와야 합니다. 이제부터 import numpy as np를 생략하겠습니다.

아마 가장 많이 사용할 방식이 바로 넘파이 배열 np.array([.......])입니다. 이를 설명하자면 그냥 배열입니다. 넘파이의 기능을 사용하지 않으면 말이죠. 꿀은 바로 넘파이의 산술연산과 배열 변환입니다. 

산술 연산을 말 그대로 넘파이 배열로 선언한 친구를 특정 값과 연산을 시키든 다른 넘파이 배열과 연산을 시키는 것입니다. 주의할 점은 넘파이 배열끼리 연산을 할 때는 반드시 두 배열의 크기가 같아야 합니다. 

x = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
x+y
x-y
x*y
x/y

x * 2.0

위와 같이 단순 +-*/만 사용해도 인덱스 끼리 해당 연산이 일어납니다.

 

다차원 배열은 생략하고 브로드캐스트를 설명하면서 같이 진행하겠습니다.

브로드캐스트란 만약 작은 단위가 더 큰 단위와 연산이 된다면 작은 단위의 값이 큰 단위의 값과 같은 형태로 형태가 바뀌어서 더욱 편하게 연산작업을 한다는 것입니다. 부등호로 표시하자면 배열 > 수, 다차원 배열 > 1차원 배열 등이 있죠. 

만약 [1, 2, 3, 4, 5]의 넘파이 배열에 2를 더한다면 2는 이제 단순히 2가 아니라 [2, 2, 2, 2, 2]의 넘파이 배열로 형태가 바뀌어 인덱스끼리 연산을 이룬다는 것입니다. 

 

6. matplotlib

matplotlib는 시각화에 주 목적을 두고 있습니다. 

matplotlib는 주로 pyplot 모듈을 사용합니다. (pylab과 동일한 기능 하는데 그냥 pyplot 쓰는 게 나음)

matplotlib는 각 함수의 기능들을 설명하기 보단 코드를 보고 직관적으로 이해하는 것이 빠를 것입니다.

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1) # 0에서 6까지 0.1간격으로
y = np.sin(x)

plt.plot(x,y)
plt.show() # 출력

이는 우리가 알고 있는 sin그래프를 그리는 코드입니다. 여기서 arange와 plot 등으로 범위와 축을 조정하여 정밀한 그래프를 그립니다. 

y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label="sin")
plt.plot(x, y2, linestyle="--", label="cos")
plt.xlabel("x") # x축 이름
plt.ylabel("y") # y축 이름
plt.title('sin & cos') # 제목
plt.legend()
plt.show()

위 코드 결과

좀 더 복잡하게 sin과 cos을 같이 그리되 선의 형태를 조정해주면 위 그림과 같이 나옵니다. 

matplotlib는 그래프 뿐만 아니라 이미지를 표시할 수도 있습니다. 

이는 imread()메서드를 통해 실행됩니다. 

from matplotlib.image import imread

img = imread('love.JPG')

plt.imshow(img)
plt.show()

위에 넣은 jpg 파일의 자리에는 그냥 본인이 가지고 있는 이미지 파일의 이름과 파일 형태를 넣으면 됩니다.

 

 

 

 

이상으로 머신러닝과 딥러닝을 하는 데 있어서 필요한 가장 기본적인 파이썬에 대한 기초 지식들을 알아봤습니다. 

가장 생소한 것은 외부 라이브러리인 넘파이와 matplotlib일 것 같은데 간략하게 설명해놓은지라 방대한 내용을 다루지 않았습니다.

댓글