파이썬을 이용하여 난수를 발생시키거나 데이터를 무작위로 섞는 방법에 대해 알아본다.
이런 기능들은 주로 NumPy의 random 서브패키지에서 제공한다.
In [1]:
import numpy as np
컴퓨터 프로그램에서 무작위와 관련된 모든 알고리즘은 사실 무작위가 아니라 시작 숫자를 정해 주면 그 다음에는 정해진 알고리즘에 의해 마치 난수처럼 보이는 수열을 생성한다. 다만 출력되는 숫자들 간의 상관관계가 없어 보일 뿐이다.
또한 같은 알고리즘을 여러번 실행하더라도 다른 숫자가 나오도록 시작 숫자는 현재 시간 등을 사용해서 매번 바꿔준다. 이런 시작 숫자를 시드(seed)라고 한다.
따라서 시드를 사람이 수동으로 설정한다면 그 다음에 만들어지는 난수들은 예측할 수 있다.
파이썬에서 시드를 설정하는 명령은 seed
이다. 인수로는 0과 같거나 큰 정수를 넣어준다.
In [2]:
np.random.seed(0)
이렇게 시드를 설정한 후 rand
명령으로 5개의 난수를 생성해 보자. 다른 난수 관련 명령어를 실행하지 말고 바로 다음 명령을 실행해야 한다.
In [3]:
np.random.rand(5)
Out[3]:
몇번 더 난수를 생성한다.
In [4]:
np.random.rand(10)
Out[4]:
In [5]:
np.random.rand(10)
Out[5]:
이제 시드를 0으로 재설정하고 다시 난수를 발생시켜 본다.
In [6]:
np.random.seed(0)
In [7]:
np.random.rand(5)
Out[7]:
In [8]:
np.random.rand(10)
Out[8]:
In [9]:
np.random.rand(10)
Out[9]:
아까와 같은 숫자가 나오는 것을 확인할 수 있다.
기존에 있는 데이터의 순서를 바꾸려면 shuffle
명령을 사용한다.
In [10]:
x = np.arange(10)
np.random.shuffle(x)
x
Out[10]:
이미 있는 데이터 집합에서 일부를 선택하는 것을 샘플링(sampling)이라고 한다. 샘플링에는 choice
명령을 사용한다. choice
명령은 다음과 같은 인수를 가질 수 있다.
numpy.random.choice(a, size=None, replace=True, p=None)
In [11]:
np.random.choice(5, 5, replace=False) # shuffle 명령과 같다.
Out[11]:
In [12]:
np.random.choice(5, 3, replace=False) # 3개만 선택
Out[12]:
In [13]:
np.random.choice(5, 10) # 반복해서 10개 선택
Out[13]:
In [14]:
np.random.choice(5, 10, p=[0.1, 0, 0.3, 0.6, 0]) # 선택 확률을 다르게 해서 10개 선택
Out[14]:
NumPy의 random 서브패키지에는 난수를 생성하는 명령이 4가지가 있다.
rand
: 0부터 1사이의 균일 분포 randn
: 가우시안 표준 정규 분포randint
: 균일 분포의 정수 난수rand
명령은 0부터 1사이에서 균일한 확률 분포로 실수 난수를 생성한다. 숫자 인수는 생성할 난수의 크기이다. 여러개의 인수를 넣으면 해당 크기를 가진 행렬을 생성한다.
In [15]:
np.random.rand(10)
Out[15]:
In [16]:
np.random.rand(3, 5)
Out[16]:
randn
명령은 기댓값이 0이고 표준편차가 1인 가우시안 표준 정규 분포를 따르는 난수를 생성한다. 인수 사용법은 rand
명령과 같다.
In [17]:
np.random.randn(10)
Out[17]:
In [18]:
np.random.randn(3, 5)
Out[18]:
randint
명령은 다음과 같은 인수를 가진다.
numpy.random.randint(low, high=None, size=None)
만약 high
를 입력하지 않으면 0과 low
사이의 숫자를, high
를 입력하면 low
와 high
는 사이의 숫자를 출력한다. size
는 난수의 숫자이다.
In [19]:
np.random.randint(10, size=10)
Out[19]:
In [20]:
np.random.randint(10, 20, size=10)
Out[20]:
In [21]:
np.random.randint(10, 20, size=(3,5))
Out[21]:
이렇게 발생시킨 난수가 실수값이면 히스토그램 등을 사용하여 분석하면 된다.
만약 난수가 정수값이면 unique
명령이나 bincount
명령으로 데이터 값을 분석할 수 있다. 이 명렬들은 random 서브패키지가 아니라 NumPy 바로 아래에 포함된 명령이다.
unique
명령은 데이터에서 중복된 값을 제거하고 중복되지 않는 값의 리스트를 출력한다. return_counts
인수를 True 로 설정하면 각 값을 가진 데이터 갯수도 출력한다.
In [22]:
np.unique([11, 11, 2, 2, 34, 34])
Out[22]:
In [23]:
a = np.array(['a', 'b', 'b', 'c', 'a'])
index, count = np.unique(a, return_counts=True)
In [24]:
index
Out[24]:
In [25]:
count
Out[25]:
그러나 unique
값은 데이터에 존재하는 값에 대해서만 갯수를 세므로 나올 수 있음에도 불구하고 데이터가 하나도 없는 값에 대한 정보를 주지 않는다.
따라서 데이터가 주사위를 던졌을 때 나오는 수처럼 특정 범위안의 수인 경우에는 bincount
에 minlength
인수를 설정하여 쓰는 것이 더 편리하다. 이 때는 0 부터 minlength
- 1 까지의 숫자에 대해 각각 카운트를 한다. 데이터가 없을 경우에는 카운트 값이 0이 된다.
In [26]:
np.bincount([1, 1, 2, 2, 2, 3], minlength=6)
Out[26]: