Numpy(넘파이)

Jaho·2021년 12월 1일
0

Python

목록 보기
5/18
post-custom-banner

넘파이(Numpy)란?

1.행렬이나 일반적으로 대규모 다차원 배열을 쉽게 처리 할 수 있도록 지원하는 파이썬의 라이브러리
2.데이터 구조 외에도 수치 계산을 위해 효율적으로 구현된 기능을 제공
출처 : 위키피디아

  • 넘파이(numpy)를 사용하면 파이썬에서 행렬과 그 밖의 수치를 쉽고 빠르게 처리할 수 있다.

  • Numeric Python = numpy

  • 통계 기반 머신러닝과 신경망 기반 딥러닝 = 행렬연산 + 통계 + 수치해석 등 도움이 된다.

  • 넘파이랑 함께 사용할 수 있는 프로그램(패키지) = Scipy + Pandas + matplotlib

  • Scipy : 수치 해석 패키지

  • Pandas : 표(table) 연산 패키지

  • matplotlib : 그래프 표시 처리 패키지

  • <<하이퍼 파라미터를 난수로 발생해서 대입할 때 사용할 내용의 함수를 넘파이 구현한다.>>

배열(array)

파이썬 배열의 특징 : 리스트(list)로 관리

  • 배열의 크기를 자유롭게 늘리고 줄인다.
  • 각 원소의 크기가 고정되어 있지 않다.
  • 동적 배열(dynamic array)라고 부른다.
    (내부적으로 전통적 의미의 배열로 처리)
  • 배열 요소에 index 부여
  • 각종 배열 메서드를 사용한다.
  • 즉 파이썬 배열 = 파이썬 리스트 이다. array = list

배열 다루기

1차원 배열

list01 = [1,2,3,4]
print(list01)

[1,2,3,4]

2차원 배열

list02 = [[1,2,3,4], [5,6,7,8]]

[[1,2,3,4], [5,6,7,8]]

3차원 배열

list03 = [[[1,2,3,4], [5,6,7,8]],
			[['가','나','다','라'],['마','바','사','아']]]

[[[1,2,3,4], [5,6,7,8]],[['가','나','다','라'],['마','바','사','아']]]

x차원 쉽게 알아보는 방법
가 1개 = 1차원
[[]] = 2차원
[[[]]] = 3차원

넘파이의 기본

1.파이썬에서는 배열(array)이라는 데이터 형식을 지원하지 않으므로 리스트(list)를 사용해 전통적인 의미의 배열을 사용

2.리스트는 포인터 기반 리스트 그래프 구조로 형성되어 컴퓨터 메모리 상에서 흩어져 있게 되지만, 넘파이 배열은 C 언어와 마찬가지로 컴퓨터 메모리의 연접 공간에 배열을 넣고 관리하기 때문에, ✔파이썬 리스트보다 처리 속도 면에서 비교할 수 없을 정도로 빠르다.

3.리스트를 만들 때 각 성분의 데이터 형식이 달라도 되지만, 넘파이 배열에서는 💡각 성분의 데이터 형식이 같아야한다.

넘파이 배열 형성

# (1) 넘파이 배열을 만들려면 먼저 리스트 형식으로 배열을 구성해 준다. 
리스트형_배열 = [1, 2, 3, 4, 5]  # 우변은 배열 정의 부분, =은 할당 연산.
print(리스트형_배열)

[1,2,3,4,5]

# (2) 그러고 나서 리스트 형식 배열을 넘파이 배열로 캐스팅한다. 
넘파이형_배열 = np.array(리스트형_배열)
print(넘파이형_배열)

[1 2 3 4 5]
cmd에서의 값 = array([1, 2, 3, 4])

넘파이 배열의 데이터 형식

1.넘파이 배열의 데이터 형식은 'ndarray' 이다.
2.n차원 배열(n-dimensional array)이라는 뜻을 지닌 이름

# [보충] 넘파이형 배열의 데이터 형식(data type, 자료형) 알아보기
type(넘파이형_배열)

<class 'numpy.ndarray'>

리스트 값을 넣어 배열 형성하기

1차원 리스트 값을 바로 넣어 넘파이 형식 배열 형성하기

넘파이형_1차원_배열 = np.array([1, 2, 3, 4, 5])
print(넘파이형_1차원_배열)
print(type(넘파이형_1차원_배열))

[1 2 3 4 5]
<class 'numpy.ndarray'>

넘파이는 데이터 형식을 자동으로 변경 해준다.

넘파이형_1차원_배열02 = np.array([1, 2.1, 3.1, 4, 5])
print(넘파이형_1차원_배열02)
print(type(넘파이형_1차원_배열02))
print(넘파이형_1차원_배열02.tolist())

int와 float이 섞여있을 경우 float 형식으로 변형
[1. 2.1 3.1 4. 5. ]
<class 'numpy.ndarray'>
[1.0, 2.1, 3.1, 4.0, 5.0]

1차원 데이터를 1~10 까지의 값을 ndarray로 만들어서 중간 값 분산,최대,최소값을 출력해보자.

res = np.array(range(1,11))
print(res.mean(), res.var(), res.sum(), res.max(),res.min())
print(res)

print('tobytes = ', res.tobytes()) #byte로변환
print('tolist = ',res.tolist()) #list로 변환

res02 = res.tolist() #res복사하여 list로 변환
print(type(res02))  # list 타입

mean() = 중간 값
var() = 분산
sum() = 합
max() = 최대 값
min() = 최소 값

5.5 8.25 55 10 1
[ 1 2 3 4 5 6 7 8 9 10]
tobytes = b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00'
tolist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
<class 'list'>

2차원 리스트 값을 넣어 넘파이 형식으로 된 2차원 배열을 형성하기

넘파이형_2차원_배열 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(넘파이형_2차원_배열)

[[ 1 2 3 4 5][ 6 7 8 9 10]]

3차원 리스트 값을 넣어 넘파이 형식으로 된 3차원 배열을 형성하기

넘파이형_3차원_배열 = np.array([[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]], [[1.0, 2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0, 10.0]]])
print(넘파이형_3차원_배열)  # 각 수치가 모두 부동소수점 형식으로 통일되었다는 점에 주목하자.

[[[ 1. 2. 3. 4. 5.][ 6. 7. 8. 9. 10.]]
.
[[ 1. 2. 3. 4. 5.][ 6. 7. 8. 9. 10.]]]

넘파이 배열의 크기와 데이터 형식

넘파이 형식으로 된 배열을 보통 넘파이 배열이라고 부른다.

배열 크기 확인 -> 형태 -> 모양 (수학용어 ,행렬의 모양 shape of array)

print(넘파이형_1차원_배열.shape)
print(넘파이형_2차원_배열.shape)
print(넘파이형_3차원_배열.shape)

(5,) = 5행
(2, 5) = 2열,5행
(2, 2, 5) = 2열, 2열, 5행

배열 차원 확인

print(넘파이형_1차원_배열.ndim)
print(넘파이형_2차원_배열.ndim)
print(넘파이형_3차원_배열.ndim)

1
2
3
ndim = 배열 차원 확인(몇 차원인가?)

빈 배열을 넣으면 그대로 3차원일까?

test01 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[]]])
print(test01.ndim)

test01은 몇차원일까?
.
답은 2차원이다.
빈 리스트는 포함하지않는 것 같다.

배열(을 이루고 있는 원소)의 데이터 형식 확인

print(넘파이형_1차원_배열.dtype)
print(넘파이형_2차원_배열.dtype)
print(넘파이형_3차원_배열.dtype)  # 각 원소의 데이터 형식이 float 형식이라는 점에 주목  <- 알아둘 것!

# 신경망의 뉴론간의 연결을 가중치로 표현을 실수로 한다.   가중치는 신경세포간의 연결 신호 강도 비율 이다. 0.1234 -> 1234 64bit-> 16bit  메모리 1/4로 줄이면서 신경망을 구성할 수 있다.  

int64는 정수형(64비트로 표현), float64는 소수점 수(실수형, 64비트로 표현)
int64
int64
float64
.
cmd : int32 (로 출력되서 나왔다.)
float은 동일

넘파이 부울 배열

부울_배열 = np.array([True, False, True, 1, 0])
print(부울_배열)  #  (1 0 1 1 0)  -> 벡터 연산 (컬러이미지) ->  흑백이미지로 변환 -> 연산작업 / 컬러이미지 -> 분할(28*28)  ->    연산
# 특징 잡기 / 노이즈 ( None / 중복데이터 ) 제거할 때 사용
print(부울_배열.shape)
print(부울_배열.dtype)

'[1 0 1 1 0]'
(5,)
int64
상삼각행렬, 하 삼각행렬등을 활용한 행렬 연산(특히 영상 처리)에 자주 쓰여요 그리고 행렬에서 특정 자료를 찾아 내거나 (인덱싱) 뽑아내거나 (슬라이싱) 해야 할 때 많이 사용한다.

넘파이 문자열 배열

문자열_배열 = np.array([["우리는 A반", "우리는 B반"],
                        ["Class 1", "Class 2"]])

print(문자열_배열)
print(문자열_배열.shape)
print(문자열_배열.dtype)   # 문자열의 경우 데이터 형식이 상황에 따라 다르다.
                           # 하지만 의미가 없다.

[['우리는 A반' '우리는 B반']
.
['Class 1' 'Class 2']]
(2, 2)
< U7

ex 02) dtype을 확인 해보자

x = np.array ([1.,2,3])
x.dtype

x= np.array([1,2,3], dtype='f')
x.dtype  # float32

#한 데이터 형식에서 다른 데이터 형식으로 정의된 배열의 데이터 형식을 변경하는 메소드 astype

x= x.astype(np.float64)
x.dtype

dtype('float64')

특수한 배열 형성

수치 처리를 하다 보면 0으로 채워진 배열이나 1로만 채워진 배열이나 수열로 이뤄진 배열이 필요할 때가 있다.
넘파이를 사용하면 이런 배열을 아주 쉽게 형성할 수 있다.

전체 원소가 0인 배열 형성

# 0으로만 이뤄진 1차원 배열
print(np.zeros(5))            # 💡따로 지정하지 않으면 float 형으로 형성된다.

[0. 0. 0. 0. 0.].
default : float
영행렬, 단위행렬(1로 채워진 행렬) 1차원 배열 = 벡터 / 2차원 행렬 / 3차원은 텐서
0이 무려 5개!!!

0으로만 이뤄진 1차원 정수형 배열

print(np.zeros(5, dtype=int)) # 데이터 형식을 따로 지정할 수 있다.

[0 0 0 0 0].
dtype = int64

0으로만 이뤄진 2차원 정수형 배열

print(np.zeros((2, 2), dtype=int))

[[0 0]
.
[0 0]]

0으로만 이뤄진 3차원 정수형 배열

print(np.zeros((2, 2, 2), dtype=int))

[[[0 0][0 0]]
.
[[0 0][0 0]]]

참고로 메모리 크기까지도 지정할 수 있다.
이에 대해서는 넘파이 공식 매뉴얼을 보자.

팔비트_배열 = np.zeros(5, dtype=np.ubyte) 
print(팔비트_배열)
print(팔비트_배열.dtype)

[0 0 0 0 0].
uint8

1로만 이뤄진 배열

# 1로만 이뤄진 2차원 배열
print('---2차원---\n',np.ones((5, 3)))
print('---1차원---\n',np.ones((5)))
print('---3차원---\n',np.ones((5, 3, 3)))

dtype = float64
3차원의 값 = 5개의배열 3행 3열
코드가 너무 길어서 생략

수열로 이뤄진 배열 형성

# 종료값만 지정하는 경우(시작 값은 0, 종료 값은 9)
print(np.arange(10))      #수열로  이루어진 배열 

[0 1 2 3 4 5 6 7 8 9].
dtype = int64

시작값과 종료값만 지정하는 경우

print(np.arange(2, 10))  

[2 3 4 5 6 7 8 9].

시작값과 종료값과 단계값을 지정

print(np.arange(2, 10, 2)) # 2에서 9까지(10의-1) 2스텝씩

[2 4 6 8].

넘파이 배열 연산

넘파이의 배열은 수학의 행렬(또는 텐서)을 표현하기 위한 것이므로
넘파이에서 배열 연산을 한다는 것은 행렬 연산을 한다는 것과 거의 같다

행렬 덧셈을 위한 배열 준비

= np.ones((2, 2))
print()

[[1. 1.]
.
[1. 1.]]

배열 덧셈

=+print()

[[2. 2.]
.
[2. 2.]]

배열 뺄셈

=-print()

[[0. 0.]
.
[0. 0.]]

배열 곱셈

사 = 이 * 이 
print(사)

 #곱셈  = 스칼라 곱

[[4. 4.]
.
[4. 4.]]

배열 나눗셈

=/print()

[[2. 2.]
.
[2. 2.]]

배열 나머지

나머지 =% (-)
print(나머지)

[[2. 2.]
.
[2. 2.]]

하다 보면 dtype이 float이라는 것을 눈치 챘을 것이다.

배열 나머지

나머지 =% (-)
print(나머지)

[[1. 1.]
.
[1. 1.]]

브로드캐스팅

기본적으로 크기가 같은 배열끼리 연산을 할 수 있고, 크기가 서로 다른 배열이라면 브로드캐스팅(broadcasting) 기능을 사용해 연산

큰_일 = np.ones((2, 2))  # 배열의 크기 (2, 2) 
print(큰_일)

[[1. 1.]
.
[1. 1.]]

작은_일 = np.ones((2))   # 배열의 크기 (2,)
print(작은_일)

[1. 1.].

print(큰_일 + 작은_일)  # 작은_일의 배열 크기가 (2, 2)로 조정되고
                        # 💡확장된 부분을 기존 배열 원소값으로 채운 후 연산

[[2. 2.]
.
[2. 2.]]

스칼라 연산

행렬에 스칼라값을 가지고 연산할 수 있듯이 넘파이 배열에 스칼라 값을 가지고 연산

print(* 2)

[[8. 8.]
.
[8. 8.]]

print(- 4)

[[0. 0.]
.
[0. 0.]]

배열 인덱싱

넘파이 배열에서 인덱싱을 하는 방법은 파이썬에서 리스트 등을 대상으로 인덱싱을 하는 방법과 같다

일반적인 인덱싱

 # 1차원 배열 인덱싱
일차원_배열 = np.array([2, 4, 8, 10])
print(일차원_배열


[ 2 4 8 10].

print(일차원_배열[0])   # 스칼라 값이 나온다.

2

데이터 = 일차원_배열[0]
type(데이터)

numpy.int64

print(일차원_배열[:1])  # 행렬 값이 나온다.
print('\n')

[2].

데이터2 = 일차원_배열[:1]
type(데이터2)

numpy.ndarray

print(일차원_배열[-1])  # 스칼라 값이 나온다.
print(일차원_배열[-1:]) # 💡행렬 값이 나온다.
print('\n')
print(일차원_배열[2:5])
print(일차원_배열[:3])
print(일차원_배열[1:])  # start : end-1 : step

10
[10]
.
.
[ 8 10][2 4 8]
[ 4 8 10]

2차원 배열 인덱싱

이차원_배열 = np.array([[2, 4, 8, 10], [3, 5, 7, 9]]) 
print(이차원_배열[1, 1])  # 2행 2열 값이 출력된다.
print(이차원_배열[0, 3])  # 1행 4열 값이 출력된다.

5
10

print(이차원_배열[:, 2])  # 각 행의 3열 값이 출력된다.
print(이차원_배열[1, :])  # 2행이 모두 출력된다.

[8 7].
[3 5 7 9]

[보충] 부울 인덱싱

# 부울 값 기반 인덱싱에 쓸 배열들을 준비한다.
모수_배열 = np.array([1, 2, 3, 4, 5])
print(모수_배열)
부울_배열_1 = np.array([True, False, True, False, True])
부울_배열_2 = np.array([1, 0, 1, 0, 1]) # 💡인덱싱을 할 때는 부울 값을 1, 0으로 표기하면 안 된다. 
                                        # 이것은 '정수 인덱싱'이라고 부르는 방법이기 때문이다. 
print(부울_배열_2)
print(모수_배열[부울_배열_1]) # 🔍바른 방식이다. 
print(모수_배열[부울_배열_2]) # 🔍문제가 생긴다. 
#~~~~~~! 중요하다  

[1 0 1 0 1].
[1 3 5]. = True만 출력
[2 1 2 1 2] = 인덱스가 출력

[보충] 정수 인덱싱

모수_배열 = np.array([1, 2, 3, 4, 5])
정수형_인덱스_배열 = np.array([0, 2, 3]) # 각 원소가 인덱스 값으로 쓰인다.

print(모수_배열[정수형_인덱스_배열])
# 출력을 해 보면 모수_배열의 0번째 원소(즉, 1), 
# 2번째 원소(즉, 3), 3번째 원소(즉, 4)가 출력되는 점을 볼 수 있다.

[1 3 4] = 정수 인덱싱

배열 슬라이싱

넘파이 배열 슬라이싱도 리스트 슬라이싱과 크게 다르지 않다.

이차원_배열 = np.array([[2, 4, 8, 10], [3, 5, 7, 9]]) 

print(이차원_배열[0, :]) # 첫 번째 행 전부
print(이차원_배열[:, 0]) # 첫 번째 열 전부
print(이차원_배열[0, 1:]) # 첫 번째 행의 두 번째 열부터 마지막 열까지 

[ 2 4 8 10].
[2 3].
[ 4 8 10]

넘파이가 제공하는 메서드

난수 생성

# 두 배열을 연산할 때 배열간의 차원이 다르게 지정되어 크기를 맞추게 된다. = ValueError

# 브로드 캐스트 배열의 각 차원의 크기는 입력 배열에서 해당 차원의 가장 큰 값과 동일하다.

# 입력된 배열은 각 차원의 크기가 입력의 큰 배열의 크기와 같고 확장된 크기로 계산된다.
# ex) 결손 값(null) 포함한 노이즈 값을 처리할 때 다양한 값들로 값의 균형을 맞추어 채우게 되는 경우가 발생된다.
# ex) 데이터의 학습 결과가 모두 100%에 근접한 결과를 초래하게 되면 역순으로 파이프라인을 따라 값을 조정해서 재학습(미분)을 기준으로 하게 된다.
# 이 때 값을 조정하는 부분에서 난수를 채울 때 사용한다.   ( 100 = 100% / 데이터 줄여봐 , 데이터 늘려봐 ... )
# ex) 흑백 이미지 노이즈

# 코드를 실행할 때마다 행렬 원소 값이 달라진다. 
난수_배열 = np.random.randn(5, 5) # 2차원
print(난수_배열)

난수_배열 = np.random.randn()
난수_배열

5행5열로 난수 생성
1행 난수생성

임의의 값을 이용해서 두개의 배열을 선언하여 + 연산을 해보자.

a = np.random.randint(0,10,(2,1,3)) # 0 : 10-1까지 ,  (면,행,열) 1,3개짜리의 2개
b = np.random.randint(0,10,(3,1)) # 3행 1열

print('a:\n',a)
print('\n a.shape : ',a.shape)

print('b:\n',b)
print('\n b.shape : ',b.shape)

print('a:\n',a)
print('\n a.shape : ',a.shape)
.
print('b:\n',b)
print('\n b.shape : ',b.shape)
.
.
a:
[[[6 1 6]]
.
[[3 7 9]]]
.
a.shape : (2, 1, 3)
b:
[[8][3]
[7]]
.
b.shape : (3, 1)

c= a+b
print('a+b:\n',c)
print('\n np.shape :',c.shape)

a와b 의 난수들 끼리의 합 출력
np.shape : (2, 3, 3)

새로운 차원의 값을 삽입할 수 있다.

print(b)
print(np.newaxis)
print('\n O.S b.shape :',b.shape)
b_ex = b[np.newaxis, :,:] # 차원 값 생성
print('\n Added new axis to the top :',b_ex.shape)
print(b_ex)

b_ex02 = b[:,np.newaxis,:] #차원 값 생성( 순서는 마음대로 지정할 수 있는 것 같다.)
print('\n Added new axis to the top :',b_ex02.shape)
print(b_ex02)

b 출력
None
.
O.S b.shape : (3, 1)
. Added new axis to the top : (1, 3, 1)
.
b_ex 출력 = 2차원
.
Added new axis to the top : (3, 1, 1)
b_ex02 출력 = 3차원

기본 연산

절댓값 구하기

절댓값_배열 = np.abs(난수_배열)
print(절댓값_배열)

절댓값 출력

지수와 로그 연산

print(np.sqrt(절댓값_배열), '\n')   # 제곱근 구하기
print(np.square(절댓값_배열), '\n') # 제곱 구하기
print(np.exp(절댓값_배열), '\n')    # 자연 대수 구하기
print(np.log(절댓값_배열), '\n')    # 자연 로그 구하기
print(np.log10(절댓값_배열), '\n')  # 상용 로그 구하기
print(np.log2(절댓값_배열), '\n')   # 밑이 2인 로그 구하기

삼각함수 연산

새_난수_배열 = np.random.randn(2, 2)
print(np.cos(새_난수_배열), '\n') # 코사인 함수
print(np.sin(새_난수_배열), '\n')  # 사인 함수
print(np.tan(새_난수_배열), '\n')  # 탄젠트 함수

# 이 밖에도 sinh, cosh, tanh, arcsin, arccos, arctan, arcsinh, arccosh, arctanh가 구비되어 있다. 

행렬 간 연산

# 연산에 쓸 정수 행렬 두 개를 생성한다.           
# 예측값 : 빈도 ,특정범위의 숫자, 발생확률, 클래스 등이 될 수 있다. (반드시 데이터 변형작업  = 캘리브레이션 (calibration))
# ML 모델은 데이터에서 특정 샘플에 대한 특정 값이 라고 예측한다.
# x축은 예측 값, y축은 실제 값으로 그려낸다.



행렬_1 = np.random.randint(5, size=(5, 5))  # 0 ~ 4 사이 난수 생성     균등 분포  (최대값 , 사이즈 )
행렬_2 = np.random.randint(5, size=(5, 5)) # 정수형 균등 분포를 형성한다.  

print(행렬_1)
print('\n')
print(행렬_2)

행렬 간 사칙연산

print(np.add(행렬_1, 행렬_2), '\n')       # 덧셈
print(np.subtract(행렬_1, 행렬_2), '\n')  # 뺄셈
print(np.multiply(행렬_1, 행렬_2), '\n')  # 곱셈  

행렬 간에 나눗셈을 할 때의 문제

print(np.divide(행렬_1, 행렬_2))    # 나눗셈   ㅠ infinit  = 무한대       # nan    a number   = 수가 아니다.  

#중간에  0으로 나눈값이 존재 한다. 

[[0.66666667 1.5 1.5 3. 1. ][1.33333333 0.5 1. 1.5 0.5 ]
[0.5 0. inf 1.5 1. ][1. inf 1. 1.33333333 0. ]
[0. 1. 1. 0. 1.5 ]]
값 중에 inf = infinit 즉 무한대를 뜻함,
nan = 수가 아님

💡행렬 간에 나눗셈을 할 때는 0으로 나누는 경우 등이 생길 수 있다

행렬 간의 최댓값/최솟값 구하기

print(np.maximum(행렬_1, 행렬_2), '\n')    # 최댓값
print(np.minimum(행렬_1, 행렬_2), '\n')    # 최솟값

통계 연산

넘파이를 사용하면 행렬에 대한 각종 통계량(stats)을 쉽게 알 수 있다

머신러닝, 딥러닝 = 수리통계 , 통계학 , 수학
내장 = embedding
Guassian model = 가우스 모형 , 가우스 혼합

연산에 쓸 정수 행렬 한 개를 생성한다.

행렬 = np.random.randint(20, size=(5, 5)) 
print(행렬)

0 ~ 19 사이 난수 생성

성분별 합계 구하기

print(np.sum(행렬), '\n')           # 전체 성분의 합
print(np.sum(행렬, axis = 0), '\n') # 행 성분의 합
print(np.sum(행렬, axis = 1), '\n') # 열 성분의 합

평균, 표준편차, 분산, 중앙값 계산하기 : 탐색적 데이터 분석시 사용

print(np.mean(행렬), '\n')    # 전체 성분의 평균 
print(np.var(행렬), '\n')     # 전체 성분의 분산
print(np.std(행렬), '\n')     # 전체 성분의 표준편차
print(np.median(행렬), '\n')  # 전체 성분의 중위수

사분위수 구하기

print(np.percentile(행렬, 0), '\n') # 전체 성분의 최솟값
print(np.percentile(행렬, 25), '\n') # 전체 성분의 1/4분위 위치 값 
print(np.percentile(행렬, 50), '\n') # 전체 성분의 2/4분위 위치 값 
print(np.percentile(행렬, 75), '\n') # 전체 성분의 3/4분위 위치 값 
print(np.percentile(행렬, 100), '\n') # 전체 성분의 4/4분위 위치 값  = 최댓값

최댓값, 최솟값 구하기

print(np.max(행렬), '\n') # 전체 성분의 최댓값
print(np.min(행렬), '\n') # 전체 성분의 최솟값

난수 처리

시드 값 정하기

시드(seed)란 우리 말로 하면 '씨앗'으로 번역될 수 있는 말로, 여러 차례에 걸쳐 난수를 생성할 때 매번 같은 난수가 생성될 수 있도록 하기 위한 시촛값에 해당 이 값을 정해두면 코드가 새로 실행될 때마다 난수가 바뀌지 않기 때문에, 코드가 항상 동일한 결과를 낼 수 있게 할 수 있다. 즉, 코드의 재현성에 필수인 기능이다.

시드를 정하지 않고 난수를 거듭 발생시키는 경우

# 매번 다른 결과가 나온다. 
print(np.random.rand(5), '\n')
print(np.random.rand(5), '\n')

똑같은 시드 값을 정해 난수를 거듭 발생시키는 경우

# 매번 같은 값이 나온다.  모의 데이터 실험시 매번 모의 데이터가 같아야 비교를 한다.  
np.random.seed(0)  # 시드 값을 정할 때는 0 이상인 정수로 지정한다.
print(np.random.rand(5), '\n')

np.random.seed(0)
print(np.random.rand(5), '\n')

[0.5488135 0.71518937 0.60276338 0.54488318 0.4236548 ]
.
[0.5488135 0.71518937 0.60276338 0.54488318 0.4236548 ]
두 난수들이 같은 값으로 나온다.

난수 생성

균일 분포 배열 형성

# 크기가 5인 일차원 균일 배열(즉, 벡터 또는 일차 텐서) 형성
# 이때 각 성분의 범위는 0 ~ 1
일차원_균일분포_배열 = np.random.rand(5)  
print(일차원_균일분포_배열)
print('\n')

크기가 5 X 5인 이차원 균일분포 배열(즉, 행렬 또는 이차 텐서) 형성

# 이때 각 성분의 범위는 0 ~ 1
이차원_균일분포_배열 = np.random.rand(5, 5)  #균일 분포   randn() -> normal  =정규분포  
print(이차원_균일분포_배열)

각 성분 값이 정수로 된 2차원 균일 분포 배열 형성

print(np.random.randint(20, size = 20), '\n')  # 0 ~ 19 사이 정수 균일분포 형성
print(np.random.randint(20, 40, size = 20), '\n') # 20 ~ 39 사이 정수 균일분포 형성
print(np.random.randint(20, 40, size = (4, 5)), '\n') # 20 ~ 39 사이 2차원 균일 분포 형성  size = 4행 5열

각 성분 값이 정수로 된 3차원 균일 분포 배열 형성

print(np.random.randint(10, size = (2,3,4))) 

0~9까지 2면 3행 4열로 난수생성

표준정규분포(기댓값이 0, 표준편차가 1인 분포)를 따르는 1차원 배열 형성 : 표준분포로 초기화하게 되면 인공지능이 필용하다.

일차원_표준정규분포_배열 = np.random.randn(5)  # 크기가 5인 벡터
print(일차원_표준정규분포_배열)

표준정규분포(기댓값이 0, 표준편차가 1인 분포)를 따르는 2차원 배열 형성

이차원_표준정규분포_배열 = np.random.randn(5, 5)  # 크기가 5X5인 행렬 형성
print(이차원_표준정규분포_배열)

데이터 임의표본추출

표본추출(sampling)이라는 말을 컴퓨터과학을 포함해 다양한 이과/공과 계열 학문에서는 샘플링이라고 부르는 경우도 많지만, 향후 인공지능 구현 시에 통계학에서 유래한 개념들이 많이 쓰이므로(딥러닝도 마찬가지) 앞으로 표본추출이나 표집이라고 부른다(어감에 차이가 있지만 무시). 임의표본추출(random sampling),
즉 임의표집이란 모집단(population)에서 아무렇게나 표본(sample)을 선택해추출(sampling)한다는 말

일차원 표본추출 배열 형성

표본추출_배열 = np.random.choice(10, 5)  # 모집단은 0~9, 벡터 크기는 5
print(표본추출_배열)

이차원 표본추출 배열 형성

표본추출_배열 = np.random.choice(10, (5, 5))  # 모집단은 0~9, 행렬 크기는 5X5
print(표본추출_배열)

[참고] flatten() 메서드를 사용해 행렬을 벡터로 만들기 = 시계열

print(표본추출_배열.flatten()) # 행렬  -> 벡터       평탄화     flattening  한줄로 늘여 뜨린다. 

[9 0 8 1 6 9 7 1 4 9 8 6 7 5 7 8 5 1 4 7 8 7 7 9 9] 한줄로 출력한다.

기존 행렬을 모집단으로 사용하는 경우

# ***위에 출력되지 않은 값이 전혀 나오지 않는다는 점을 잘 살펴보자.***
새_표본추출_배열 = np.random.choice(표본추출_배열.flatten(), (3, 5))  # 모집단은 0~9, 행렬 크기는 3X5
print(새_표본추출_배열)

[[5 4 7 0 2].
[0 7 4 3 2].
[9 1 6 4 0]]
행렬의 크기를 재정의 하는 느낌

각 데이터의 선택 확률을 지정해 표본추출해서 배열을 형성하기

#choice()이 세번째 매개 인자는 확률이 되는 경우를 100%로 나누어서 인덱스로 관리한다.
# 모집단은 0~2, 행렬 크기는 10 X 10
# p(0)=0.0, p(1)=0.9, p(2)=0.1
표본추출_배열 = np.random.choice(3, size=(10, 10), p=[0.1, 0.8, 0.1])    #0이 뽑힐 확률 10%   1이 출력될 확률은 80%  2가 출력될 확률은 10%
print(표본추출_배열)  

0~2까지 10행10열 형으로 0=10%, 1=80%, 2=10% 확률로 추출하여 출력한다.

출력 결과를 보면 0이 표본추출되지 않고 주로 1이 표본추출되며, 간간이 2가 표본추출된 것을 볼 수 있습니다.

정수 데이터 분석

우리는 앞에서 정수 성분으로 이뤄진 분포를 형성해 본 적이 있다. 그런데 성분의 개수가 굉장히 많다면 해당 분포에서 다시 데이터를 추출해 탐색해 보는 일이 필요

파이썬 -> 넘파이 . 파이썬 ->머신러닝/ 딥러닝 -> 머신 -> 딥러닝

크기가 5 X 95인 2차원 배열 형성

새_분포 = np.random.randint(100, size=(5, 95))  # 모집단 0~ 99  에서 중복 추출 후 새로운 분포를 만들자 정수형 균일 분포 , 복원 추출 
print(새_분포)

고윳값(unique value, 중복되지 않은 값) 찾기

# 주의: 차원축소 방법에서 말하는 고윳값(eigenvalue)과 혼동하지 말 것
# 데이터 -> 수치 -> 카테고리 별로 -> 분류 -> 
성분_값, 성분별_개수 = np.unique(새_분포, return_counts=True)
print(성분_값)
print(성분별_개수) # 자연어 처리시에  추출 중복되지 않은 어절 

성분값 = 0~99까지 나열
성분별
개수 = 중복되지 않은 값

성분별 개수를 알고 싶지 않은 경우에는 return_counts=False라고 지정하거나

# return_counts를 지운다. 
성분_값 = np.unique(새_분포)
print(성분_값)

[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 65 66 67 68 69 70 71 72 73
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 97 98]

[참고 코드] 성분 값과 성분별 개수를 튜플 형태로 짝을 짓기

# list 함수를 사용해 행렬(넘파이 배열)을 리스트로 캐스팅하고
# zip 함수를 사용해 두 리스트를 튜플 형태로 짝 지은 다음에
# 다시 리스트 형태로 만들어(파이썬 3에서는 이렇게 한 단계 더 거쳐야 함)
# 출력한다.
print(list(zip(list(성분_값), list(성분별_개수)))) 

[(0, 8), (1, 4), (2, 3), (3, 5), (4, 4), (5, 9), (6, 9), (7, 4), (8, 3), (9, 3)...]

3.7 데이터 섞기

수치 처리를 하다 보면 난수 형성만으로는 충분하지 않을 때가 있다. 우리가 만든 데이터나 난수를 아무렇게나 섞어야 할 때가 있다. 넘파이의 numpy.random.shuffle()을 사용하면 이렇게 할 수 있다

1차원 배열 섞기

# 먼저 1차원 배열을 만들어 보자. 
배열 = np.arange(10)
print(배열, '\n')

# 그리고 이 행렬을 섞어 보자.
np.random.shuffle(배열)
print(배열, '\n')

[0 1 2 3 4 5 6 7 8 9]
.
[0 4 5 1 3 2 9 8 6 7]

2차원 이상인 배열 섞기

배열 = np.arange(25).reshape(5, 5) # 5x5 2차원으로 변경 
print(배열, '\n')

np.random.shuffle(배열) # 셔플
print(배열, '\n')

[[ 0 1 2 3 4].
[ 5 6 7 8 9].
[10 11 12 13 14].
[15 16 17 18 19].
[20 21 22 23 24]]
.
[[20 21 22 23 24].
[ 5 6 7 8 9].
[ 0 1 2 3 4].
[10 11 12 13 14].
[15 16 17 18 19]]

[참고 코드] 2차원 이상인 배열에 대해서 그 성분을 온전히 다 섞어야 한다면?

# 이럴 때는 배열을 1차원으로 만들어(평탄화를 해서) 섞은 다음에 
# 다시 3차원 꼴로 편성하는 요령을 발휘하면 된다.
일차원_배열 = 배열.flatten()
print(일차원_배열, '\n')

np.random.shuffle(일차원_배열)
print(일차원_배열, '\n')

이차원_배열 = 일차원_배열.reshape(5, 5)
print(이차원_배열, '\n')

배열을 1차원(벡터)로 변경
셔플
배열 2차원으로 재정의

기타 연산

# 그 밖의 연산에 쓸 새 난수를 생성해 두자. 
새_난수_배열 = np.random.randn(3, 3)
print(새_난수_배열)

3행3열 난수생성

각 성분의 부호 알아내기

# 음수는 -1, 영은 0, 양수는 1로 나옴
print(np.sign(새_난수_배열)) 

올림과 내림

print(np.ceil(새_난수_배열), '\n')    # 소수점 이하 첫 번째 자리에서 올림
print(np.floor(새_난수_배열), '\n')   # 소수점 이하 첫 번쨰 자리에서 내림

성분이 NaN(수치가 아님)인 경우 알아내기

# 먼저 NaN이 나올 만한 연산을 한다.
print(np.sqrt(새_난수_배열), '\n') 

# NaN 성분을 알아낸다. 
print(np.isnan(np.sqrt(새_난수_배열)), '\n')

[[ nan nan 0.15117834].
[ nan nan 1.06074929].
[0.74970285 nan 0.10679901]]
.
[[ True True False].
[ True True False].
[False True False]]
.
nan 이면 True 반환


[ : 1차원
[[ : 2차원
[[[ : 3차원
np.array() : 넘파이 배열형성
1차,2차,3차원 가능
shape : 넘파이 배열의 크기 확인 (행렬의 모양)
ndim : 넘파이 배열의 차원 확인
dtype : 데이터 형식 확인 ex) int64 , float64
np.zeors() : 0으로만 이뤄진 배열 형성 , dtype : (default) float형식
np.ones() : 1로만 이뤄진 배열 형성 , dtype : (default) float형식
np.arange() : 수열로 이뤄진 배열 형성
np.random.rand() : 난수 생성 ex) 디폴트는 1차원 ,2,2 = 2차원 난수 생성
np.abs() : 절댓값 연산
np.choice : 표본 추출
np.flatten : 행렬을 백터로 만듬 (평탄화)
zip : 튜플로 묶는다.

브로드캐스팅 : 같은 배열끼리 연산
스칼라 연산 : 넘파이 배열에 스칼라 값을 가지고 연산
배열 인덱싱 : 넘파이 배열에서 인덱싱 (파이썬의 인덱싱과 같음)


profile
개발 옹알이 부터
post-custom-banner

0개의 댓글