Programming/Python

Python 기초 공부 - 7 (numpy)

Joon09 2021. 3. 9. 18:31
반응형

numpy 계산만 진행합니다.

# flask : 웹 서버 기능, 5000번 포트로 서비스

import matplotlib # 시각화 패키지
import numpy as np # 클래스로 구성되어 있다. as : 별칭

print(np.__version__) # __는 상위 오브젝트가 가지고 있는 속성이라는 의미

def pprint(arr):
    print("type : {}".format(type(arr)))
    print("shape : {}, dimension : {}, dtype : {}".format(arr.shape, arr.ndim, arr.dtype)) # 차수 3개다, 차원 1차원이다, 데이터 타입 숫자의 default는 int32
    print("Array's Data : \n",arr)
    
arr = [1.0,2.0,3.0] # list
a = np.array([1,2,3]) # ndarray : numpy의 기본 데이터 배열 , 매개변수는 리스트로 들어간다
pprint(a)

1.16.4
type : <class 'numpy.ndarray'>
shape : (3,), dimension : 1, dtype : int32
Array's Data : 
 [1 2 3]

# 인스턴스 상태에서 ndarray를 만들어보자
a = np.array([0,1,2,3,4,5,6,7,8,9])
print(id(a)) # 메모리 주소값 확인
print(a.size) # 데이터 갯수
print(a.astype(np.float32)) # astype : 데이터 타입 변경, numpy 행중심, 동질적
print(a.dtype.itemsize*a.size) # 전체 메모리 사이즈(byte) = 타입 고유의 사이즈 * 차수 수

# iterator
# range는 list를 만들고, arange는 ndarray를 만든다.
a = np.arange(100)
a

1509824915376
10
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
40
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, 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, 64, 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, 96, 97, 98, 99])

 

# ndarray 초기화 함수
print( np.zeros( (3,4) ) ) # 0 채워넣기
print( np.ones( (2,3,4), dtype = np.int16 ) ) # 1채워넣기 3차원[] 2면, 3행, 4열 ]
print( np.full( (2,2), 7) ) # 2행 x 2열 7로 채워넣기
print( np.eye(4) ) # 대각 1넣기, 대각행렬 identity 항등원 + 0 * 1
print( np.empty( (4, 2) ) ) # 쓰레기값...

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

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]]
[[7 7]
 [7 7]]
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
[[0.00000000e+000 0.00000000e+000]
 [0.00000000e+000 0.00000000e+000]
 [0.00000000e+000 4.62445445e-321]
 [1.24611470e-306 8.90060779e-307]]

a = np.arange(0, 100, 10)
indices = [1, 5, -1]
print(indices)
b = a[indices] # 리스트를 첨자로 사용
print(a)
print(b)

[1, 5, -1]
[ 0 10 20 30 40 50 60 70 80 90]
[10 50 90]

 

a = np.arange(11, 36)
print(a)
a.shape = (5,5) # 행렬은 정상모양을 갖춘 개수로 표현
print(a)
print(type(a))
print(a.dtype)
print(a.size)
print(a.shape) # 차수
print(a.ndim) # 차원
print(a.nbytes) # 100바이트 = 25개 * 4바이트
print(a.strides) # 다음 행,열의 데이터는 몇 바이트를 건너뛰는가

[11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 35]
[[11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]
 [26 27 28 29 30]
 [31 32 33 34 35]]
<class 'numpy.ndarray'>
int32
25
(5, 5)
2
100
(20, 4)

arr = np.arange(10)
print(type(arr))
print(arr)
print(arr[5])
print(arr[5:8])
arr[5:8] = 12
print(arr[1:6])

<class 'numpy.ndarray'>
[0 1 2 3 4 5 6 7 8 9]
5
[5 6 7]
[ 1  2  3  4 12]

# numpy 첨자생략 불가 [,4] 이런 것 안됨

arr2d = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
print(arr2d[0]) # 행우선 이니 0행 출력
print(arr2d[0][2]) # 0행 2열
print(arr2d[0,2])
print(arr2d[:2]) # 0,1행
print(arr2d[:2,1:])
print(arr2d[:,1:]) # :는 모든 행
print(arr2d[1,:2])
print(arr2d[2,:1])
arr2d[:2, :1] = 0
arr2d[:2, :1] = 0
print(arr2d)

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

 

사람이 데이터를 다루는 것은 입체로 하나, 실제 메모리에는 일렬로 저장

행렬연산에서의 앞의 행렬열수와 뒤의 행렬 행수를 일치시켜야 행렬곱이 가능하므로,
행렬곱에서 행렬의 계산 순서를 바꾸면 안됨

print("스트라이드의 값", np.ones((3,4,5), dtype=np.float64).strides )

스트라이드의 값 (160, 40, 8)

 


단일데이터가 float64 : 8바이트

40 = 5열 * 8바이트
160 = 4행 * 5열 * 8바이트

 

# 문제
arr3d = np.array([ [[1,2,3], [4,5,6]], [[7,8,9],[10,11,12]] ]) # 2, 2, 3
print("첫 면은 = ", arr3d[0])
print("첫 면의 첫행은 = ", arr3d[0,0])
print("첫요소는 = ", arr3d[0,0,0])

# 8을 출력해봅시다
print(arr3d[1,0,1])
# 12를 출력해봅시다
print(arr3d[1,1,2])

첫 면은 =  [[1 2 3]
 [4 5 6]]
첫 면의 첫행은 =  [1 2 3]
첫요소는 =  1
8
12

# 백업이 안됨 : 대입하면 같은 주소를 가리키기 때문
old_values = arr3d # 대입 : 주소를 복사
arr3d[0] = 42
print("값의 변경 후")
print(arr3d,'\n')
print(" 이전 값으로 복구")
arr3d = old_values
print(arr3d,'\n')

# old_values = arr3d.copy() # 값을 복사
# arr3d[0] = 42
# print("값의 변경 후")
# print(arr3d,'\n')
# print(" 이전 값으로 복구")
# arr3d = old_values
# print(arr3d,'\n')

값의 변경 후
[[[42 42 42]
  [42 42 42]]

 [[ 7  8  9]
  [10 11 12]]] 

 이전 값으로 복구
[[[42 42 42]
  [42 42 42]]

 [[ 7  8  9]
  [10 11 12]]] 

값의 변경 후
[[[42 42 42]
  [42 42 42]]

 [[ 7  8  9]
  [10 11 12]]] 

 이전 값으로 복구
[[[42 42 42]
  [42 42 42]]

 [[ 7  8  9]
  [10 11 12]]] 

Z = np.arange(36)
print(Z,'\n')
Z = Z.reshape((6,6))
reshape2 = Z.reshape((2,3,6))
print(reshape2)

[ 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 30 31 32 33 34 35] 

[[[ 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]
  [30 31 32 33 34 35]]]

arr = np.arange(32).reshape((8,4))
print(arr,'\n')
print(arr[[1,5,7,2]],'\n') # 행중심
print(arr[[-1,-5,-7,-2]],'\n')
print(arr[ [1,5,7,2], [0,3,1,2] ],'\n')

# fancy 인덱싱
print(arr[[1,2,5,7]] [:,[0,1,2,3]],'\n')
print(arr[[1,5,7,2]] [:,[0,3,1,2]])

[[ 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 30 31]] 

[[ 4  5  6  7]
 [20 21 22 23]
 [28 29 30 31]
 [ 8  9 10 11]] 

[[28 29 30 31]
 [12 13 14 15]
 [ 4  5  6  7]
 [24 25 26 27]] 

[ 4 23 29 10] 

[[ 4  5  6  7]
 [ 8  9 10 11]
 [20 21 22 23]
 [28 29 30 31]] 

[[ 4  7  5  6]
 [20 23 21 22]
 [28 31 29 30]
 [ 8 11  9 10]]

 

arr = []
for i in range(6):
    ad = []
    for j in range(6):
        ad.append( i*10 + j )
    arr.append(ad)
print(arr)
arr = np.array(arr)

# 빨간거
print(arr[[0,2,5],2]); print()

# 주황색
print(arr[[0,1,2,3,4],[1,2,3,4,5]]); print()

# 옥색
print(arr[3:6][:,[0,2,5]])

[[0, 1, 2, 3, 4, 5], [10, 11, 12, 13, 14, 15], [20, 21, 22, 23, 24, 25], [30, 31, 32, 33, 34, 35], [40, 41, 42, 43, 44, 45], [50, 51, 52, 53, 54, 55]]
[ 2 22 52]

[ 1 12 23 34 45]

[[30 32 35]
 [40 42 45]
 [50 52 55]]

 



# 문제2

# 빨간거
print(arr[:,2]); print()

# 주황
print(arr[0,[3,4]]); print()

# 녹
print(arr[[2,5]][:,[0,2,4]]); print()

# 청녹
print(arr[4:][:,[4,5]]); print()

[ 2 12 22 32 42 52]

[3 4]

[[20 22 24]
 [50 52 54]]

[[44 45]
 [54 55]]

 

x = np.array([ [1,2,3], [4,5,6], [7,8,9], [10,11,12] ]) # 4x3
v = np.array([1,0,1])
print("타일출력\n")
vv = np.tile(v,(4,1)) # 화장실 타일처럼 복사시키기
print(vv,'\n')
y = x + vv # 4행3열 배열연산[요소별로 연산 +-*/]     배열연산과 행렬연산은 다르다!!!!!!
print(y,'\n\n')
# 배열연산은 양쪽 차원이 일치해야한다
print(x + v,'\n')# 4x3, 1x3 의 연산이 되나? broadcasting! 행이나 열의 수가 같아야!
print(x + 3)

타일출력

[[1 0 1]
 [1 0 1]
 [1 0 1]
 [1 0 1]] 

[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]] 


[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]] 

[[ 4  5  6]
 [ 7  8  9]
 [10 11 12]
 [13 14 15]]

x = np.arange(6).reshape((3,2))
print(x)
# 거듭제곱(행렬곱)
#x @ x # 앞의 열수와 뒤의 행수가 일치해야 한다
# (3x2) (3x2)

# 전치행렬
x@x.T # (3x2) (2x3)

print(np.transpose(x)) # 행렬을 바꾸어준다

[[0 1]
 [2 3]
 [4 5]]
[[0 2 4]
 [1 3 5]]

arr = np.arange(24).reshape((2,3,4)) # 0,1,2
print(arr)
print('\n\n\n')
print(arr.transpose((1,0,2))) # 3x2x4
print('\n\n\n')
print(arr.transpose((0,2,1))) # 2x4x3

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

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]




[[[ 0  1  2  3]
  [12 13 14 15]]

 [[ 4  5  6  7]
  [16 17 18 19]]

 [[ 8  9 10 11]
  [20 21 22 23]]]




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

 [[12 16 20]
  [13 17 21]
  [14 18 22]
  [15 19 23]]]

 

BOOLEAN INDEXING (TRUE/FALSE)

names = np.array(['Seoul', 'Daejun', 'chungju', 'seoul', 'chungju', 'Daejun', 'Daejun'])
data = np.random.randn(7,4)
print(names == 'Seoul') # 문자열은 대소문자 구분함  # T,F,F,F,F,F,F
print(data[names=='Seoul']) # True인 것만 출력
print(data[names=='Seoul', 2:])
print(data[names=='Seoul', 3])
print(names != 'Seoul') # F,T,T,T,T,T,T
print(~(names=='Seoul')) # F,T,T,T,T,T,T
mask = (names=='Seoul') | (names=='chungju')
print(mask)
print(data[mask])

[ True False False False False False False]
[[ 0.42095613  0.17597758 -0.05644088 -1.10524404]]
[[-0.05644088 -1.10524404]]
[-1.10524404]
[False  True  True  True  True  True  True]
[False  True  True  True  True  True  True]
[ True False  True False  True False False]
[[ 0.42095613  0.17597758 -0.05644088 -1.10524404]
 [-0.03307741 -0.87156314 -0.52807885  0.60578028]
 [ 1.37052914  1.3105813   0.5604668  -0.30676522]]

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])

print(zip(xarr, yarr, cond)) # zip : 요소별로 데이터를 묶음
print(list(zip(xarr, yarr, cond)))
result = [(x if c else y) for x,y,c in zip(xarr, yarr, cond)] # 3항연산자
print("result = ",result)

result = np.where(cond, xarr, yarr)
print(result)

arr = np.random.randn(4,4)
print(arr)
print(np.where(arr>0, 2, -2))

<zip object at 0x0000015DC12E0048>
[(1.1, 2.1, True), (1.2, 2.2, False), (1.3, 2.3, True), (1.4, 2.4, True), (1.5, 2.5, False)]
result =  [1.1, 2.2, 1.3, 1.4, 2.5]
[1.1 2.2 1.3 1.4 2.5]
[[-0.43115124  0.31799955 -0.71370485  0.36621282]
 [-1.67870128  0.91579184 -0.4281239  -2.15582502]
 [-1.22680744 -1.59959683 -0.29502866  0.04495333]
 [ 0.55818941  0.20412896 -0.02008031  0.1374442 ]]
[[-2  2 -2  2]
 [-2  2 -2 -2]
 [-2 -2 -2  2]
 [ 2  2 -2  2]]

# 문제 : 다음 데이터를 이용하여
# 두개 다 참일 때는 0,
# cond1이 참일 때는 1,
# cond2가 참일 때는 2
# 그 외일 때는 3으로 처리하여 출력하도록 하시오

result = []
cond1 = np.array([1,0,1,1,0,0,1], dtype=bool)
cond2 = np.array([0,1,1,1,0,1,1], dtype=bool)

# 조건문으로 하면 4가지
for i in range(len(cond1)):
    if(cond1[i] and cond2[i]):
        result.append(0)
    elif cond1[i]:
        result.append(1)
    elif cond2[i]:
        result.append(2)
    else:
        result.append(3)
        
# where로 풀면
result = np.where(cond1 & cond2, 0, np.where(cond1, 1, np.where(cond2, 2,3)))

# 수식을 이용하면
result = 1*(cond1&~cond2) + 2*(cond2&~cond1) + 3*~(cond1|cond2)

# 내가 해본 것은
result = [(0 if (a&b)|(~(a|b)) else (1 if a else (2 if b else 3)) )  for a,b in zip(cond1,cond2)]
print(result)

[1, 2, 0, 0, 0, 2, 0]

x = np.arange(1, 10001)
y = np.arange(10001, 20001)
z = np.zeros_like(x) # 파라메터[다른 행렬]와 같은 사이즈로 초기화

for i in range(10000):
    z[i] = x[i] + y[i]
print(z)

[10002 10004 10006 ... 29996 29998 30000]

 

a = np.array([1,2,3,4])
b = np.array([4,2,2,4])
print(np.all(a==b)) # 전체가 참일 때 참
print(np.any(a==b)) # 하나라도 참이면 참
print(np.exp(a)) # 지수함수( 자연대수 : 2.718)

False
[ 2.71828183  7.3890561  20.08553692 54.59815003]


선형대수 : 문제를 선형으로 해결하자 => 비선형도 잘게 나누면 선형

 

행렬의 종류
- 정방행렬 : 정사각형(행, 열의 수가 같은 행렬)
- 대칭행렬 : 우상단과 좌하단이 같은 것
- 대각행렬 : scale을 변화시키는 요소
- 단위행렬(identity) :  행렬곱의 항등원, 행렬과 역행렬을 곱하면 단위행렬나옴.
- 역행렬 : 행렬의 나눗셈을 위해 구해서 곱해지는 행렬[정방행렬만 가능]
- 특이행렬 : 역행렬이 없는 행렬
- 직교행렬 : 축의 정직교, 각축간의 내적이 0인 행렬
- 정방행렬이면서 대칭행렬 : 공분산행렬, 상관계수행렬, 거리행렬
- 공분산 : 두 수 사이의 관계, ((한 수-평균) * (다른 수-평균)) / (n-1)
                                    # 제곱한 효과
- 상관계수(표준화 -1 ~ 1) : 공분산 / 표준편차의 곱


import numpy as np

F1 = np.array([[1,2], [3,4]])
F2 = np.array([[2,2], [2,2]])
print(F1)
print(F2)
print(F1+F2) # 요소끼리
print(F1*F2)
print(F1@F2) # 행렬곱도 내적이다. 두 벡터의 사이각을 구해
# 1,2   2,2      6,6
# 3,4   2,2     14,14   

# 차원을 축소하여 특징을 추출할 때 한번에 해버리면 데이터 소실이 심하므로, 차원축소를 여러횟수로 나눠서 한다. 이를 딥러닝이라 한다.
# 예) 100개 -> 2개... (X)      100개 -> 50개 -> 2개 (O)

# 1,2,  2,2,1
# 3,4   2,2,1      차원확장도 가능

[[1 2]
 [3 4]]
[[2 2]
 [2 2]]
[[3 4]
 [5 6]]
[[2 4]
 [6 8]]
[[ 6  6]
 [14 14]]

 

# 문제
# 방정식의 해
# 2x1 + x2 -2 x3 = -3
# 3x1 +       x3 = 5
#  x1 + x2-   x3 = -2
A = np.array([[2,1,-2], [3,0,1], [1,1,-1]])
print(A)
b = np.transpose(np.array([[-3,5,-2]])) # 열로 전치
print(b)
x = np.linalg.solve(A,b) #A의 역행렬을 구해서 b와 곱해줌
print(x)

[[ 2  1 -2]
 [ 3  0  1]
 [ 1  1 -1]]
[[-3]
 [ 5]
 [-2]]
[[ 1.]
 [-1.]
 [ 2.]]

 

linalg = 선형대수학

np.dot(np.linalg.inv(A),b) # A의 역행렬을 구해서 b와 행렬곱

array([[ 1.],
       [-1.],
       [ 2.]])

np.linalg.inv(A)@b # 왜 역행렬을 구해야 하는가? 행렬은 나눗셈이 없기 때문에 역행렬을 곱해서 해결한다

array([[ 1.],
       [-1.],
       [ 2.]])

# 검산
2*1  +  (-1) + -2*2

-3

 

a = np.array([0,1,0]) # y축
b= np.array([1,0,0]) # x축
res = np.dot(a,b) # 내적 사이각 = 직각
print(res)

0

print(np.linalg.norm(a)) # 벡터의 크기
print(np.linalg.norm(b))
print(np.linalg.norm(a) * np.linalg.norm(b))
rad = res / (np.linalg.norm(a) * np.linalg.norm(b)) # cos(theta) 값을 구함
print("cos theta", rad)
print(np.arccos(rad)) #theta 값을 구함
print(np.degrees(np.arccos(rad))) # 사람이 알아보는 각도로 표현

1.0
1.0
1.0
cos theta 0.0
1.5707963267948966
90.0

x = np.array([[1,2], [3,4]])
y = np.linalg.inv(x)
print(x)
print(y)
print(np.dot(x,y))

[[1 2]
 [3 4]]
[[-2.   1. ]
 [ 1.5 -0.5]]
[[1.00000000e+00 1.11022302e-16]
 [0.00000000e+00 1.00000000e+00]]

# 다음 방정식의 해를 구하고 검산하시오
x + y + z = 6
2y + 5z = -4
2x + 5y -z = 27
x = np.array([[1,1,1],[0,2,5],[2,5,-1]])
y = np.transpose(np.array([6,-4,27]))
print(x); print()
print(y); print()
print(np.linalg.solve(x,y))

[[ 1  1  1]
 [ 0  2  5]
 [ 2  5 -1]]

[ 6 -4 27]

[ 5.  3. -2.]

반응형