본문 바로가기

😀 기초/넘파이(NumPy)

3장 난수 발생과 카운팅(3.5)

3.5 난수 발생과 카운팅

 

1. 난수 발생과 카운팅

- 파이썬을 이용하여 데이터를 무작위로 섞거나 임의 수(난수)
- 이 기능은 주로 NumPy의 random 서브페키지에서 제공

 

2. 시드 설정하기
- 컴퓨터 프로그래밍에서 무작위 수는 사실 무작위 수가 아니다.
- 정해진 알고즘에 의해 난수처럼 보이는 수열을 생성
- 이런 시작 숫자를 시드(seed)라고 한다.
- 일단 생성된 난수는 다음번 난수 생성을 위한 시드값이 된다.
- 따라서 시드값은 한 번만 정해주면 된다.
- 시드는 보통 현재 시각등을 이용하여 자동으로 정해지지만 사람이 수동으로 설정할 수 있다.
- 특정한 시드값이 사용되면 그 다음에 만들어지는 난수들은 모두 예특할 수 있음
- 이 책에서는 코드의 결과를 재현하기 위해 항상 시드를 설정한다.

# - 파이썬에서 시드를 설정하는 함수는 seed이다.
# - 인수로는 0과 같거나 큰 정수를 넣어준다.

np.random.seed(0)

- 이렇게 시드 설정 후 넘파이 radnom 서브패키지에 있는 rand함수로 5개 난수 생성해보자
- rand 함수는 0과 1사이의 난수를 발생시키는 함수로 인수로 받은 숫자 횟수 만큼 난수 발생

np.random.rand(5)
#결과
array([0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 ])


np.random.rand(10)
#결과

array([0.64589411, 0.43758721, 0.891773  , 0.96366276, 0.38344152,
       0.79172504, 0.52889492, 0.56804456, 0.92559664, 0.07103606])
       
# 이제 시드를 0으로 재설정하고 다시 난수 발생.

np.random.seed(0)

np.random.rand(5)
#결과
array([0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 ])

np.random.rand(10)
#결과
array([0.64589411, 0.43758721, 0.891773  , 0.96366276, 0.38344152,
       0.79172504, 0.52889492, 0.56804456, 0.92559664, 0.07103606])

- 아까와 같은 숫자가 나온 것을 확인

 

3. 데이터의 순서 바꾸기
shuffle 함수 사용
- shuffle 함수도 자체 변환(in-place)함수로 한 번 사용하면 변수의 값이 바뀌므로 주의!

x = np.arange(10)
x

#결과
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

np.random.shuffle(x)
x
#결과
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

np.random.shuffle(x)
x
#결과
array([5, 1, 8, 2, 6, 7, 0, 3, 4, 9])

4. 데이터 샘플링
- 이미 있는 데이터 집합에서 일부를 무작위로 선택하는 걸 샘플링이라고 함.
choice함수 이용
- numpy.random.choice(a, size=None, replace=True, p=None)
- a : 배열이면 원래의 데이터, 정수이면 arange(a) 명령으로 데이터 생성
- size : 정수. 샘플 숫자
- replace : 불리언. True이면 한번 선택한 데이터를 다시 선택 가능
- p : 배열. 각 데이터가 선택될 수 있는 확률

np.random.choice(5, 5, replace=False)  # shuffle 명령과 같다.

#결과
array([4, 2, 3, 1, 0])

np.random.choice(5, 3, replace=False) # 3개만 선택
#결과
array([1, 4, 2])

np.random.choice(5, 10) # 반복해서 10개 선택
#결과
array([3, 3, 2, 4, 2, 0, 0, 4, 0, 4])

np.random.choice(5, 10, p=[0.1, 0, 0.3, 0.6, 0]) # 선택 확률을 다르게 해서 10개 선택
#결과
array([3, 3, 3, 2, 3, 2, 3, 3, 3, 0])

5. 난수 생성
random 서브패키지는 이외에도 난수 생성하는 다양한 함수 제공
- 그 중 가장 간단하고 많이 사용되는 3가지 함수
- rand : 0부터 1사이의 균일 분포
- randn : 표준 정규 분포
- randint : 균일 분포의 정수 난수

 

- rand 함수는 0부터 1사이에서 균일한 확률 분포로 실수 난수 생성

np.random.rand(10)

#결과
array([0.6228461 , 0.67365963, 0.971945  , 0.87819347, 0.50962438,
       0.05571469, 0.45115921, 0.01998767, 0.44171092, 0.97958673])
    
np.random.rand(3, 5)
#결과
array([[0.35944446, 0.48089353, 0.68866118, 0.88047589, 0.91823547],
       [0.21682214, 0.56518887, 0.86510256, 0.50896896, 0.91672295],
       [0.92115761, 0.08311249, 0.27771856, 0.0093567 , 0.84234208]])

- randn함수는 기댓값이 0이고 표준편차가 1인 표준 정규 분포

np.random.randn(10)
# 결과
array([ 0.99982969,  0.43103415, -0.65091287, -1.49874039, -1.23063497,
        0.19400719, -0.99838235, -0.3676376 ,  1.73719932,  0.59361275])

np.random.randn(3, 5)
# 결과
array([[-0.54236358, -1.71967238, -0.57890879,  1.42694855,  0.27699691],
       [ 0.78966713,  0.32207411,  0.70039238,  0.38871663, -0.04126386],
       [ 0.29588432, -0.42527999,  1.72763912, -0.86835257, -0.82097758]])

- randint 함수는 다음과 같은 인수를 가진다.
- numpy.random.randint(low, high=None, size=None)
- 만약 high를 입력하지 않으면 0과 low사이를 숫자를,
- high를 입력하면 low와 high는 사이의 숫자를 출력
- size는 난수의 숫자이다.

np.random.randint(10, size=10)
# 결과 
array([9, 0, 9, 6, 5, 3, 1, 8, 0, 4])

np.random.randint(10, 20, size=(3, 5))
# 결과
array([[19, 16, 15, 17, 18],
       [18, 19, 12, 18, 16],
       [16, 19, 11, 16, 18]])

6. 정수 데이터 카운팅
- 이렇게 발생시킨 난수가 실수값이면 히스토리그램 등을 사용하여 분석
- 나중에 시각화 부분에서 히스토그램을 배울 예정

- 만약 난수가 정수값이면 unique 명령이나 bincount 명령으로 분석

 

- unique 함수는 데이터에서 중복된 값을 제거하고 중복되지 않는 값의 리스트를 출력
-return_counts 인수를 True로 설정하면 각 값을 가진 데이터 갯수도 출력한다.

np.unique([11, 11, 2, 2, 34, 34])
# 결과 
array([ 2, 11, 34])


a = np.array(['a', 'b', 'b', 'c', 'a'])
index, count = np.unique(a, return_counts=True)

index
# 결과
array(['a', 'b', 'c'], dtype='<U1')

count
# 결과
array([2, 2, 1], dtype=int64)

- 그러나 unique 함수는 데이터에 존재하는 값에 대해서만 갯수를 세므로 데이터 값이 나올 수 있음에도 불구하고 데이터가 하나도 없는 경우에는 정보를 주지 않는다.
- 예를 들어 주사위를 10번 던졌는데 6이 한 번도 나오지 않으면 이 값을 0으로 세어주지 않는다.

 

- 따라서 데이터가 주사위를 던졌을 때 나오는 수처럼 특정 범위안의 수인 경우에는
- bimcount 함수에 minlength 인수를 설정하여 쓴느 것이 더 편리
- bincount 함수는 0 부터 minlength -1 까지의 숫자에 대해 각각 카운트를 한다.
- 데이터가 없을 경우에는 카운트 값이 0이 된다.

np.bincount([1, 1, 2, 2, 2, 3], minlength=6)

#결과
array([0, 2, 3, 1, 0, 0], dtype=int64)