[7호] 넘파이(Numpy)와 함께 땅따먹기를-01
인문학적 시선으로 인공지능 파헤치기-07
과거의 문학도이자 현재의 공학도, 그리고 아티스트인 한 사람이 인공지능에 대해 알려주는 글을 연재한다. 전문용어의 단순한 나열이 아닌, 사람들의 공감을 불러일으키는 방향으로. 언제나 그랬듯, 지능의 발달은 공감에서 출발하기 때문.
되새기기
지난 시간부터 넘파이(Numpy)와 친해지기 위해 노력하고 있다. 넘파이의 중요성을 충분히 알았다면 이제 다음 단계로 나아가자. 만약 넘파이를 배우지 않은 채 빨리 인공지능이나 배우고 싶다면 잠깐의 시간을 들여 이전 글을 읽고 돌아오기 바란다.
데이터 타입
데이터 타입(data type, 주로 dtype로 표기된다)은 중요한 개념 중 하나다.
컴퓨터 내장메모리에 여러 개의 방이 있다고 상상해 보자. 각 방에 들어갈 수 있는 크기는 정해져 있으며 데이터의 종류에 따라 여러 개의 방을 전세낼 수 있다. 여기서는 제일 접하기 쉬운 정수형 데이터, 즉 int(정수를 뜻하는 integer의 준말)를 예시로 설명하겠다.
컴퓨터 언어는 성격에 따라, 변수를 저장할 때 이 변수 안에 어떤 데이터 타입이 들어갈 예정인지 미리 알려줘야 하는 언어와 그렇지 않은 언어로 나뉜다. C++이나 자바는 개발자가 변수 앞에 자료형을 붙여야 한다. 그래야 메모리에 방 몇 개를 예약할 것인지 정할 수 있기 때문이다. 이와 같은 언어를 ‘정적 언어'라고 한다.
// 정적 언어로 변수 선언하기
int a = 8;
반면, 파이썬은 ‘동적 언어'다. 개발자가 자료형을 명시하지 않아도 알아서 메모리를 관리한다. 데이터 타입을 동적으로 추론하는 것이다.
# 동적 언어로 변수 선언하기. 파이썬은 스크립트 언어라 ;(세미콜론)도 필요없다.
a = 8
어떻게 이런 일이 가능할까? 항상 명심하자. 개발자가 힘들면 컴퓨터는 비교적 편하고(작업 부담이 적고) 개발자가 편하면 컴퓨터가 할 일은 많아진다. 그래서 파이썬이 C++이나 자바에 비해 느리다는 것도 이 때문이다.
파이썬의 변수는 단순히 값을 저장하는 것이 아니라 값이 저장된 메모리의 주소를 ‘가리키고' 있다. 하지만 파이썬에는 C++의 포인터(pointer, ‘가리키는 자'로 생각하면 편하다) 개념이 없으므로 변수 하나하나가 모두 객체다. 이 안에는 주소 뿐만 아니라 여러 정보들이 담겨 있는 셈이다. 객체가 하나만 있다면 상관없겠지만 긴 프로그램에서는 사정이 다르다.
a = 8
a = 'snowman'
# 정수형 데이터를 저장한 a에 문자열 저장하기(파이썬)
정수형 변수에 문자열, 즉 string값을 담는 것은 정적 언어에서는 상상도 할 수 없는 일이지만 파이썬에서는 가능하다. 우리는 그에 대한 대가가 따른다는 것도 알았다. 그렇다면 파이썬으로 어떻게 머신러닝, 딥러닝, 인공지능 연구를 편하게 할 수 있을까?
그 답은 넘파이에서 출발한다. 넘파이는 데이터 관리와 효율적인 계산법을 제공한다. 물론 ‘효율적'이라는 의미는 개발자 입장이 아니라 컴퓨터 입장에서 말하는 것이다. 따라서 넘파이 배열은 파이썬의 리스트처럼 다양한 값을 하나의 배열에 저장하지 못한다.
import numpy as npmyList = [1, [2, 3], 'counting numbers'] # 가능
np.array([1, [2, 3], 'impossible']) # 파이썬의 자료형 중 하나인 list는 다양한 값을 하나의 리스트에 저장할 수 있다.
# 반면 넘파이 배열은 위와 같이 선언하면 의도하지 않은 결과가 나온다.(노트북 참고)
이제 넘파이 배열을 만들어 보자.
넘파이 배열 만들기
위의 코드를 꼼꼼히 본 독자는 눈치챘겠지만 파이썬 리스트를 np.array()의 괄호 안에 집어넣어 넘파이 배열을 만들 수 있다.
example = np.array([1, 2, 3, 4, 5])
배열 안 요소가 모두 같은 타입이라는 것에 주목하라.
데이터 사이언스에서 이렇게 배열 안 요소를 하나하나 정하고 집어넣는 것은 가뜩이나 힘든 전처리 과정을 더욱 지루하게 만들 뿐이다. 그래서 파이썬 리스트를 넘파이 배열로 탈바꿈시키는 것보다 처음부터 넘파이 배열을 생성하는 것이 더 대중적이다.
친절한 넘파이는 거의 모든 솔루션을 제공한다. 다섯 개의 요소를 가지며 모든 배열값이 정수 0인 넘파이 배열을 만들어 보자.
np.zeros(5, dtype = int)
np.zeros()는 배열을 0으로 채우겠다는 뜻의 메소드(다른 언어에서는 함수로 칭한다)다. () 안에 패러미터로는 배열의 크기와 데이터 타입(생략 가능)이 들어간다.
만약 동일한 조건에서 1로 채우고 싶다면?
np.ones(5, dtype = int)
1을 정수형이 아니라 부동소수점 데이터(float) 형태로 채우고, 1차원 배열이 아니라 2x4의 2차원 배열로 만들고 싶다면?
np.ones((2, 4), dtype = float)
0도 아니고 1도 아니고 8로 이 2차원 배열을 도배하고 싶다면?
np.full((2, 4), 8)
이외에도 다양한 기능이 있다.
0에서 시작해 30에 도달할 때까지 3씩 건너뛰며 넘파이 배열을 생성할 수 있다.
np.arange(0, 30, 3)
30은 생성 결과에 포함되지 않는다. 끝 지점을 표현하는 척도는 배열에 들어가지 않는다는 것을 명심, 또 명심하자.
0과 30 사이에 일정한 간격을 가진 7개의 값으로 채운 넘파이 배열 만들기는?
np.linspace(0, 30, 7)
3x3 크기의 단위 행렬은?
np.eye(3)
이도저도 싫고 일단 5 크기의 배열만 만들고 싶다면?
np.empty(5)
이외에도 다양한 생성법이 존재하지만 일일이 나열하는 것보다 넘파이 문서를 참고하는 것이 더 편하다. 훌륭한 개발자는 머리에서 코드를 쏟아내는 사람이 아니라 여러 레퍼런스를 참조하며 원하는 결과를 도출하기 위해 끝까지 노력하는 사람이므로.
넘파이 배열의 호패
앞에서 파이썬 변수는 객체이며 다양한 정보를 갖고 있다고 언급했다. 그렇다면 넘파이 배열은 어떤 속성을 지니고 있을까? 또한 그 정보들을 어떻게 해야 신분증 검사를 하듯이 이끌어낼 수 있을까?
우선 넘파이 배열을 아무렇게나 하나 생성해 보자.
exp1 = np.random.randint(10, size = 5)
0부터 10 이전까지의 정수들 중 아무 것이나 5개 뽑아서 1차원 넘파이 배열을 만들었다. 이제 exp1의 정보들을 출력해 보자.
제일 기본적으로, 배열 안에 몇 개의 요소가 들어 있는지를 출력해 보자. 이 속성은 ‘배열의 크기’라고 한다.
# 배열의 크기는 (배열의 이름).size로 알아낸다.
print('배열의 크기: ', exp1.size)[]: 배열의 크기: 5
방금 필자는 이 배열더러 ‘1차원' 배열이라 칭했다. 그렇다. 넘파이 배열의 호패에는 ‘몇 차원인지에 대한 정보'도 적혀 있다. 이를 ‘차원의 개수'라 부른다.
# 배열이 몇 차원인지에 대한 정보는 (배열의 이름).ndim으로 얻어낸다.
print('몇 차원?: ', exp1.ndim)[]: 몇 차원: 1
각 차원에 대한 요소가 몇 개인지 알아보자.
print('각 차원에 대해 자세히 알기: ', exp1.shape)[]: 각 차원에 대해 자세히 알기: (5,)
(5, )가 출력되었다. 이는 파이썬 자료형에서 튜플(tuple, () 안에 하나 혹은 여러 개의 값을 보관하는 데이터 타입)이며, 튜플에서는 하나의 요소를 표현할 때 뒤에 꼭 반점을 붙인다. 안 그러면 문자열이 되어 버리기 때문이다.
이 밖에도 배열 요소 하나하나의 크기를 나타내는 itemsize와 배열의 전체 크기를 나타내는 nbytes가 있다. 이름에서 짐작할 수 있듯이 이들은 바이트 단위로 표현한다. 그리고 배열 요소 하나하나의 크기를 배열의 크기만큼 곱하면 전체 크기가 나올 것이다.
글을 맺으며.
축하한다. 글을 꼼꼼히 읽었다면 당신은 넘파이의 제일 기초적인 부분을 통달한 것이다.
이제 필자의 코랩 노트북으로 실습을 진행하길 바란다. 노트북 상단의 ‘Copy to Drive’ 버튼을 눌러 독자 여러분의 구글 드라이브에서 실행해 보시길. 숫자를 바꿔가며 실행하면 즐거울 것이다. 필자의 Github Repository에 즐겨찾기를 누르면 복습에 더욱 유용할 것이다!
다음 글 이후부터는 숲 말고 나무를 볼 것이다. 넘파이 배열의 요소 하나하나에 어떻게 접근하는지, 그리고 배열에서 또 다른 배열을 만들 수 있는지를 살펴볼 예정이다.
넘파이와 숫자놀음을 하며 땅따먹기 하기. 이왕이면 즐겁게 배워나가기를 소망한다.
박수, 댓글, 그리고 출처를 밝힌 공유는 언제나 환영합니다. 문의사항은 OCOL 메일이나 작가 개인(suyeonbb8@gmail.com)에게 남겨주시기 바랍니다.
인문학을 느끼며 인공지능 알아가기 프로젝트. 마지막까지 함께해 주세요🍪