728x90

NumPy (Numerical Python)

 

 - Array 구조의 객체 지원

 - 수학적 반복 연산을 빠르게 처리 

     * array 구조는 단 하나의 데이터 타입만 허용

     * 수학적 연산에 반복적인 벡터 연산 가능 (단, 문자 치환은 벡터 연산 불가)

 - 수학적 연산이 많은 딥러닝 수행 시 유용

     * 딥러닝 구조의 핵심 데이터 타입

 - 빠르고 효율적인 메모리 사용

 

 

# 모듈 적용

# numpy 모듈을 np로 사용                             

import numpy as np

 

 

# 생성 (.array, .arange, .random.randn)

np.array([10,20,30])

array([10, 20, 30])

 

np.arange(10)    # 0 ~ n-1 까지의 값을 갖는 1차원 배열

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

 

np.arange(5,15,2)   # n ~ m-1 까지 s 만큼의 간격의 값을 갖는 1차원 배열 

 array([ 5,  7,  9, 11, 13])

 

np.random.randn(2,3)   표준정규분포를 따르는 2차원 난수 배열 

array([[ 1.24508099,  0.29652356, -0.97754508],

       [-1.13415315,  0.73094591, -1.04153084]])

 

np.arange(10).reshape(2,5)    # 2차원 배열 

array([[0, 1, 2, 3, 4],

       [5, 6, 7, 8, 9]])

 

np.arange(24).reshape(2,3,4)   # 3차원 배열(,,), R에서는 (,,)

array([[[ 0,  1,  2,  3],

        [ 4,  5,  6,  7],

        [ 8,  9, 10, 11]],

 

       [[12, 13, 14, 15],

        [16, 17, 18, 19],

        [20, 21, 22, 23]]])

 

 

 

# 모양 변경 (.reshape)

np.arange(10).reshape(2,5)

array([[0, 1, 2, 3, 4],

         [5, 6, 7, 8, 9]])

 

 

# 2차원 배열 색인  

arr1 = np.arange(10).reshape(2,5)

array([[0, 1, 2, 3, 4],

        [5, 6, 7, 8, 9]])

 

arr1[0,2]  ==  arr1[0][2]    # 포인트 색인

2

arr1[[0,1],[1,3]]

array([1, 8])    # (0,1) (1,3) 색인

 

arr1[0]  ==  arr1[0,]  ==  arr1[0,:]     # 행 색인

 

array([0, 1, 2, 3, 4])

 

 

arr1[:,0]     # 열 색인

 

array([0, 5])

 

 

arr1[:,0:3]   # 슬라이스 색인

array([[0, 1, 2],

       [5, 6, 7]])

arr1[:2,3:]

array([[3, 4],

       [8, 9]])

 

arr1[:,[1,3]]   # 부분 색인

array([[1, 3],

       [6, 8]])

 

arr1[0,[2,3]]  ==  arr1[0][[2,3]]   

array([2, 3]))

arr1[[0,1]][:,[0,1]] 

array([[0, 1],

       [5, 6]])

 

 

 

# 3차원 배열 색인 

arr3 = np.arange(24).reshape(2,3,4)  

array([[[ 0,  1,  2,  3],

        [ 4,  5,  6,  7],

        [ 8,  9, 10, 11]],

 

       [[12, 13, 14, 15],

        [16, 17, 18, 19],

        [20, 21, 22, 23]]])

 

arr3[0]    # 층 색인 (가장 높은 차원이 우선 적용)

array([[ 0,  1,  2,  3],

       [ 4,  5,  6,  7],

       [ 8,  9, 10, 11]])

 

arr3[:,0]     # 행 색인

array([[ 0,  1,  2,  3],

       [12, 13, 14, 15]])

 

arr3[1,2,0]    # 열 색인

20

arr3[1][[0,1]][:,[0,2]]

array([[12, 14],

       [16, 18]])

 

arr3[:,0:1, 0:1]    # 슬라이스 색인 (슬라이스 사용 시 차원의 축소 방지)

array([[[ 0]],

 

       [[12]]])

 

arr3[0][[0,1],:][:,[0,1]]  ==  arr3[0:1,0:2,0:2]

array([[0, 1],      # 1층, 1,2행, 1,2열

       [4, 5]])

 

 

 

# 색인 함수 (np.ix_)

arr1 = np.arange(10).reshape(2,5)

arr1[np.ix_([0,1],[0,1])]  ==  arr1[[0,1]][:,[0,1]]  # 순차적이 아닌, 연속적 색인 가능

array([[0, 1],

       [5, 6]])

 

arr2 = np.arange(24).reshape(2,3,4) 

arr2[np.ix_([0,1],[0,2],[0,2])]  ==  arr2[[0,1]][:,[0,2]][:,:,[0,2]]  # 1,2층 / 1,3행 / 1,3열

array([[[ 0,  2],

        [ 8, 10]],

 

       [[12, 14],

        [20, 22]]])

 

 

 

# boolean 색인

arr1 = np.arange(20).reshape(4,5)

array([[ 0,  1,  2,  3,  4],

       [ 5,  6,  7,  8,  9],

       [10, 11, 12, 13, 14],

       [15, 16, 17, 18, 19]])

arr1[[True,False,True,False]]    # True 인 행 색인 (1,3행)

array([[ 0,  1,  2,  3,  4],

       [10, 11, 12, 13, 14]])

arr1[(arr1[:,3] >= 10)]     # 3번째 컬럼이 10 이상인 행 색인 

array([[10, 11, 12, 13, 14],

       [15, 16, 17, 18, 19]])

arr1[~(arr1[:,3] >= 10)]   # 위 결과의 나머지 색인 ('~' 조건의 부정)

array([[0, 1, 2, 3, 4],

       [5, 6, 7, 8, 9]])

 

 

 

# 슬라이스 색인의 뷰

a1 = np.arange(10)

a2 = a1[3:6]     # 슬라이스 색인은 원본과 동일한 메모리 영역을 사용(얇은 복사) = 뷰 객체

a2[1] = 40

a1

array([ 0,  1,  2,  3, 40,  5,  6,  7,  8,  9])

 

a1 = np.arange(10)

a2 = a1[3:6].copy()   # 원본과 메모리를 분리하기 위해 copy() 메서드 사용

a2[1] =40

a1

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

 

 

 

# 연산

# 배열 연산의 전재 조건

1) 배열 전체 크기가 동일

ar1 = np.array([10,20,30])

ar2 = np.array([100,100,100])

ar1 + ar2        (1x3, 1x3) 크기가 동일하므로 연산 가능 

array([110, 120, 130])

 

2) 같은 방향(row or column)의 크기가 동일

arr1 = np.arange(10).reshape(2,5)

arr2 = np.arange(5).reshape(1,5)

arr1 + arr2      # (2x5, 1x5) 전체 크기는 다르지만 같은 방향(column)의 크기가 동일하므로 연산 가능

                        row 수가 부족한 1x5의 배열을 반복(broadcasting) 적용

array([[ 0,  2,  4,  6,  8],

       [ 5,  7,  9, 11, 13]])

 

 

# 크기가 다른 배열을 연산하는 방법

arr1 = np.arange(10).reshape(2,5)

arr1 + arr1[:,0]     # (2x5, 1x2) 로 연산이 불가한 상황

 

1) reshape

arr1 + arr1[:,0].reshape(2,1)    # (2x5, 2x1) 로 크기를 맞추기 위해, 1x2의 배열의 모양을 변경

array([[ 0,  1,  2,  3,  4],

       [10, 11, 12, 13, 14]])

 

2) 차원의 축소 방지

arr1 + arr1[:,0:1]                # 색인 시 차원의 축소가 발생, 차원 축소 방지를 위해 슬라이스 색인을 사용

array([[ 0,  1,  2,  3,  4],

       [10, 11, 12, 13, 14]])

 

 

 

# 복사 (.array, .asarray)

l1 = [1,2,3]

arr1 = np.array(l1)     # 깊은 복사 (다른 메모리 영역 사용)

arr2 = np.asarray(l1)  # 깊은 복사 (다른 메모리 영역 사용)

arr1[0] = 10             # 리스트는 자료구조 자체가 달라지므로 모두 깊은 복사 수행 

arr2[1] = 20

l1                          # 원본 데이터는 보존

[1, 2, 3]

 

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

arr1 = np.array(arr)     # 깊은 복사 (다른 메모리 영역 사용)

arr2 = np.asarray(arr)  # 얇은 복사 (같은 메모리 영역 사용)

arr1[0] = 10

arr2[1] = 20

arr                           # asarray로 복사 후 변경한 데이터가 원본 데이터에 영향

array([ 1, 20,  3])

 

 

 

 

# Q

### 3x5 의 임시 배열을 만든 후

 

arr1 = np.zeros((3,5))

 

# 1) 첫 번째 행의 모든 데이터를 10으로 변경

 

arr1[0] = 10

 

# 2) 두 번째 행, 3,4번째 컬럼 값을 10으로 변경

 

arr1[1,[2,3]] = 10

 

# 3) (10,20,30)의 값을 갖는 배열 생성 후 위 배열과 연산(+)

 

arr2 = np.array([10,20,30])

 

arr1 + arr2.reshape(3,1)

 

###  5x4 형태의 임시 배열을 생성한 후 

arr5 = np.arange(20).reshape(5,4)

# p(1,0), p(3,1) 의 값을 출력

arr5[[1,3],[0,1]]

# 2) 위의 배열에서 arr[1:3,2:4]의 형태와 동일하게 팬시색인을 통해 출력

arr5[[1,2]][:,[2,3]]

arr5[np.ix_([1,2],[2,3])]



출처: https://data-make.tistory.com/111 [Data Makes Our Future]

728x90

numpy array의 특징과 사용법을 정리해보겠습니다.

1. np.array의 특징

  • numpy는 np.array 함수를 활용하여 배열을 생성합니다.
  • numpy는 하나의 데이터 타입만 정의가 가능하며 배열에 넣을 수 있습니다.
  • List와 가장 큰 차이점은 다이나믹 타이핑을 지원하지 않습니다.
  • C의 Array를 사용하여 배열을 생성하여 속도가 빠릅니다.

2. np.array의 구조

 

np.array와 Python list의 차이점

파이썬의 리스트는 데이터 주소값을 저장합니다. 그리고 데이터를 가져 올때는 해당 주소에 가서 데이터를 가져오게 되죠. 하지만 Numpy Array는 C 배열과 유사하여 연속된 주소를 가지고 있습니다. 배열에 담긴 데이터를 가져온다면 순서대로 가져오면 되기 때문에 메모리를 효율적으로 사용합니다.

 

3. np.array 사용법

 

import numpy as np
test_np_array = np.array([1.0,4.0,5.0,'8'], dtype=np.float)
test_np_array

#출력 : array([1., 4., 5., 8.])

np.array로 선언하고 두번째 인자로 데이터 타입을 선언합니다. 선언된 데이터로 배열이 만들어지며 입력시 다른 데이터를 입력하더라도 선언한 데이터 타입으로 변환됩니다.

 

 

dtype은 배열의 요소가 가지는 데이터 타입을 정의하며 정의된 타입에 따라 메모리 크기가 설정됩니다.

 

test_array = [1.0,4.0,5.0,'8.0'];
test_array

# 출력 : [1.0, 4.0, 5.0, '8.0']

python 리스트가 np.array와 다른 점은 입력시 다른데이터 타입을 입력하면 리스트에 입력되는 것을 확인 할 수 있습니다.

test_np_array.dtype # 배열의 타입을 반환한다.

# 출력 : dtype('float64')

test_np_array.shape # 배열의 shape을 반환함

# 출력 : (4,)

dtype : 배열의 타입을 반환

shape : 배열의 차원을 반환

tensor = [
            [[1,2,5,8],[1,2,5,8],[1,2,5,8]],
            [[1,2,5,8],[1,2,5,8],[1,2,5,8]],
            [[1,2,5,8],[1,2,5,8],[1,2,5,8]],
          ]
np.array(tensor, int).ndim # 몇차원인지 반환

# 3

np.array(tensor, int).size # 데이터의 사이즈 반환

# 36

np.array(tensor, int).nbytes # 메모리 크기 반환

# 144

ndim : 배열이 몇 차원인지 반환

size   : 배열의 데이터 사이즈 반환 

nbytes : 배열의 메모리 크기 반환

728x90

arange

 

numpy에서 원하는 숫자 범위를 모두 포함하는 배열을 만드는 함수를 제공합니다.

arange를 사용하면 원하는 숫자 범위, 숫자 간격에 따른 array를 생성할 수 있습니다.

import numpy as np;
np.arange(30) # range : List의 range와 같은 효과, integer로 0부터 29까지 배열 추출

-- 출력 -- 
array([ 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, 25, 26, 27, 28, 29])
np.arange(0, 5, 0.5) # floating point 도 표시가능함

-- 출력 -- 
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
create_array = np.arange(30);
create_array.reshape(5,6)

-- 출력 --
array([[ 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, 25, 26, 27, 28, 29]])

zeros

zeros는 0으로 가득 찬 array를 생성합니다.

 

np.zeros(shape, dtype, order)

 

np.zeros(shape=(10,), dtype=np.int8) # 10 -zero vector 생성

-- 출력 -- 
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int8)
np.zeros((2,5)) # 2 by 5 - zero matrix 생성

-- 출력 -- 
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

ones

ones는 zeros와 마찬가지로 1로 가득찬 array를 생성합니다.

 

np.ones(shape, dtype, order)

 

np.ones(shape=(10,), dtype=np.int8)

-- 출력 -- 
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)
np.ones((2,5))

-- 출력 -- 
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

empty 

empty는 초기화되지 않은 값으로 zeros나 ones와 마찬가지로 배열을 생성해줍니다.

주의해야 할 것은 메모리도 초기화되지 않기 때문에 예상하지 못한 쓰레기 값이 들어가 있습니다.

np.empty(shape=(10,), dtype=np.int8)

-- 출력 --
array([101,   0, 100,   0, 117,   0, 108,   0, 101,   0], dtype=int8)
np.empty((3,5))

-- 출력 -- 
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

something_like

 

_like는 지정된 array의 shape 크기만큼 지정된 값으로 채워 array를 반환합니다.

앞에서 정리한 ones, zeros, empty를 사용할 수 있습니다.

 

test_matrix = np.arange(30).reshape(5,6);
np.ones_like(test_matrix)

-- 출력 --
array([[1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1]])
np.zeros_like(test_matrix)

-- 출력 --
array([[0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0]])
np.empty_like(test_matrix)

-- 출력 --
array([[1611640584,        345,         71,          0,          0,
                 0],
       [         0,          0,          0,          0, 1953702523,
        1937077345],
       [1864514082,  573317739, 1667594341, 1869182069, 1868783470,
         578055797],
       [ 741488698, 1702065442, 2019909490, 1936028272, 1852795251,
        2067407475],
       [1881287805, 1869379937,  975332449,    8215899,          0,
                 0]])

empty는 메모리가 초기화되지 않고 할당되기 때문에 쓰레기 값이 있을 수 있습니다.

이 점 꼭 주의 고려하여 사용해야 합니다.

'PYTHON' 카테고리의 다른 글

[Python] Numpy 배열(생성, 색인, 연산 ..)  (0) 2020.12.09
[python] numpy array 특징과 사용법  (0) 2020.12.09
02-4 튜플 자료형  (0) 2020.12.09
Python Basic I - List  (0) 2019.03.24
Python Start <Basic Setting, IDE, Variable>  (0) 2019.03.18
728x90

튜플은 어떻게 만들까?

튜플(tuple)은 몇 가지 점을 제외하곤 리스트와 거의 비슷하며 리스트와 다른 점은 다음과 같다.

  • 리스트는 [ ]으로 둘러싸지만 튜플은 ( )으로 둘러싼다.
  • 리스트는 그 값의 생성, 삭제, 수정이 가능하지만 튜플은 그 값을 바꿀 수 없다.

튜플의 모습은 다음과 같다.

>>> t1 = ()

>>> t2 = (1,)

>>> t3 = (1, 2, 3)

>>> t4 = 1, 2, 3

>>> t5 = ('a', 'b', ('ab', 'cd'))

 

리스트와 모습은 거의 비슷하지만 튜플에서는 리스트와 다른 2가지 차이점을 찾아볼 수 있다. t2 = (1,)처럼 단지 1개의 요소만을 가질 때는 요소 뒤에 콤마(,)를 반드시 붙여야 한다는 것과 t4 = 1, 2, 3처럼 괄호( )를 생략해도 무방하다는 점이다.

얼핏 보면 튜플과 리스트는 비슷한 역할을 하지만 프로그래밍을 할 때 튜플과 리스트는 구별해서 사용하는 것이 유리하다. 튜플과 리스트의 가장 큰 차이는 값을 변화시킬 수 있는가 여부이다. 즉 리스트의 항목 값은 변화가 가능하고 튜플의 항목 값은 변화가 불가능하다. 따라서 프로그램이 실행되는 동안 그 값이 항상 변하지 않기를 바란다거나 값이 바뀔까 걱정하고 싶지 않다면 주저하지 말고 튜플을 사용해야 한다. 이와는 반대로 수시로 그 값을 변화시켜야할 경우라면 리스트를 사용해야 한다. 실제 프로그램에서는 값이 변경되는 형태의 변수가 훨씬 많기 때문에 평균적으로 튜플보다는 리스트를 더 많이 사용한다.

튜플의 요소값을 지우거나 변경하려고 하면 어떻게 될까?

앞에서 설명했듯이 튜플의 요솟값은 한 번 정하면 지우거나 변경할 수 없다. 다음에 소개하는 두 예를 살펴보면 무슨 말인지 알 수 있을 것이다.

1. 튜플 요솟값을 삭제하려 할 때

>>> t1 = (1, 2, 'a', 'b')
>>> del t1[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object doesn't support item deletion

튜플의 요소를 리스트처럼 del 함수로 지우려고 한 예이다. 튜플은 요소를 지우는 행위가 지원되지 않는다는 메시지를 확인할 수 있다.

2. 튜플 요솟값을 변경하려 할 때

>>> t1 = (1, 2, 'a', 'b')
>>> t1[0] = 'c'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

튜플의 요솟값을 변경하려고 해도 마찬가지로 오류가 발생하는 것을 확인할 수 있다.

튜플 다루기

튜플은 값을 변화시킬 수 없다는 점만 제외하면 리스트와 완전히 동일하므로 간단하게만 살펴보겠다. 다음 예제는 서로 연관되어 있으므로 차례대로 수행해 보기 바란다.

인덱싱하기

>>> t1 = (1, 2, 'a', 'b')
>>> t1[0]
1
>>> t1[3]
'b'

문자열, 리스트와 마찬가지로 t1[0], t1[3]처럼 인덱싱이 가능하다.

슬라이싱하기

>>> t1 = (1, 2, 'a', 'b')
>>> t1[1:]
(2, 'a', 'b')

t1[1]부터 튜플의 마지막 요소까지 슬라이싱하는 예이다.

튜플 더하기

>>> t1 = (1, 2, 'a', 'b')
>>> t2 = (3, 4)
>>> t1 + t2
(1, 2, 'a', 'b', 3, 4)

튜플을 더하는 방법을 보여 주는 예이다.

튜플 곱하기

>>> t2 = (3, 4)
>>> t2 * 3
(3, 4, 3, 4, 3, 4)

튜플의 곱하기(반복) 예를 보여 준다.

튜플 길이 구하기

>>> t1 = (1, 2, 'a', 'b')
>>> len(t1)
4

튜플의 길이를 구하는 예이다.

+ Recent posts