1. conda create --name 바꿀이름 --clone 기존이름

conda create --name py37_32 --clone python_env 

 

2. 복사된 가상환경 확인 

***키움 Open API 연동오류 해결 방법

AttributeError: 'QAxWidget' object has no attribute 'OnEventConnect'

 

오탈자도 없는데, 위와 같은 문제가 생겼다. 

찾아보니, bit가 안맞아서 발생하는 문제였다.

OPEN API는 32bit인데, 내가 사용하던 파이썬은 64bit이기 때문이다.

 

결론적으로는 파이썬 32bit 가상환경을 만들어서 파이참에서 사용하면 된다.

 

 

1. 아나콘다 프롬프트 실행 

(1. Anaconda Prompt) 

 

 

2. 파이썬 32비트로 설정

(2. setting 32bit python)

set CONDA_FORCE_32BIT=1

 

 

3. 파이썬 가상환경 설치

(3. install 32bit python virtual env)

가상환경이름은 주로 py37_32 와 같이 표현한다.

py : 파이썬

37 : 3.7 버전

32 : 32bit 

conda create -n py37_32 anaconda

 

 

4. 설치한 가상환경 실행

(4. activate the virtual env)

(base) 에서 (py37_32)로 변경된 것을 확인할 수 있다.

conda activate py37_32 

 

 

5. 설치된 가상환경 확인하기

(5. Check the folder of the virtual env)

Anaconda3 설치 폴더 밑에 가상환경들이 설치된 것을 볼 수 있다.

 


6. 설치한 가상환경을 Pycharm에 설정하기

(6. Setting the virtual env in Pycharm)

File - Settings 로 들어간다.

 

 

 

7. 설치한 가상환경 추가하기

(Add the virtual env)

Project - Python Interpreter - Add

 

 

 

 

8. 가상환경 열기

(8. Activate the virtual env in Pycharm)

Terminal - 

conda activate py37_32

1000장의 데이터

batch_size  = 10 

update : 100번

장점: 미세한 조정 가능

단점: 속도가 느리다 

업데이트 되는 양 자체도 작아서 초기 학습 값이 잘못되었을때 다시 되돌아 오지 못한다.

 

batch_size = 100

update : 10번

장점: 크게크게 업데이트

속도가 빠르다

 

단점: 정밀도 떨어진다

 

적절한 batch_size 찾는 법

model.fit(batch_size는 32로 디폴트 지정됨)

또는 전처리 단계에서 batch_size 설정 가능 -> 장점은 train batch 크게/ valid batch 작게 따로 설정가능

 

Train/valid data 개수 batch_size steps_per_epoch  validation_steps
1000 10 100  
200 10 20  
1024 10 1024//10 + 1  

 

반드시 정수로 나누어 떨어지게 값을 조정해야한다.

그렇지 못할 경우에는 몫에 + 1 로 값을 입력한다.

 

전체 복사 붙여넣게 금지

xs 와 ys 값이 랜덤으로 주어지므로 

#YOUR CODE HERE  

이하로만 손대기

 

import numpy as np
import tensorflow as tf


def solution_model():
    xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
    ys = np.array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0], dtype=float)
    # YOUR CODE HERE
    model = tf.keras.models.Sequential([
        tf.keras.layers.Dense(1, input_shape=[1]),
    ])
    model.compile(optimizer="sgd", loss="mse")
    model.fit(xs, ys, epochs=500, verbose=0)
    return model


# Note that you'll need to save your model as a .h5 like this
# This .h5 will be uploaded to the testing infrastructure
# and a score will be returned to you
if __name__ == '__main__':
    model = solution_model()
    model.save("mymodel.h5")
    print(model.predict([10.0]))

ctrl + m + a

위에 셀 추가

 

ctrl + m + b

아래에 셀 추가

 

ctrl + m + d

셀 삭제

 

ctrl + enter

해당 셀 실행

 

shift + enter

해당 셀 실행 후 다음 셀로 이동

 

Alt + enter

해당 셀 실행 후 아래쪽에 셀 추가

 

ctrl + m + m

해당 셀을 텍스트셀로 변환

 

ctrl + m + y

해당 셀을 코드셀로 변환

 

tensorflow 자격증 환경 세팅하기

 

1. 구글 드라이브 

새로만들기 - 더보기 - 연결할 앱 더보기

(필자는 코랩이 깔려있어서 목록에 보이는 상태)

 

2. "colab" 검색하여 설치 실행

1. 선형함수의 개념

Y = W * X + b

W : Weight : 기울기

b : bias : 절편

 

 

2. 오차를 구하는 방법

각각의 X 값 마다 오차값들을 그냥 더하기만 한다면?

오차가 0이 나올 수 있다. -> 오류가 있음

 

ㅇ MAE (Mean Absolute Error)

오차 절대값 평균

 

ㅇ MSE (Mean Squared Error)

오차 제곱 평균

문제 유형

1번문제 기본문제

2/3/4 는 분류문제 

sigmoid/ softmax둘 중 하나

 

checkpoint

 

callback = [checkpoint]

 

저장을 한 후 자동으로 

 

best epoch의 w 값을 실어주기

매 epoch 마다 loss가 더 낮게 나오면 checkpoint에 저장된다

가장 마지막 코드

model.load_weights(checkpoint_path)

 

2번은 3가지 문제 중에 한가지 랜덤하게 나옴 (2가지 유형)

1) 이미지 분류 2개 - mnist 손글씨분류 / fashion mnist

2) 정형데이터 - iris 꽃 분류문제

 

 

이미지 rescale

픽셀들을 하나씩 까서 보면 0~255 사이의 값을 가지고 있다.

 

1. 모든 픽셀 값이 0~1 사이의 값을 가지도록 하자 = Normalization

x_train = x_train / 255.0

x_valid = x_valid / 255.0

 

y는 class값임 분류 값이므로 255로 나누어서는 안된다.

이미지 데이터인 x 에 대해서만 255로 나누어 rescale을 해준다.

Normalization을 해야하는 이유?

- 데이터 분산 값을 줄여줌으로서 원하는 목표 loss 까지 수렴이 더 빨리 된다. 

 

2. OneHot Encoding

 

빨강 1

노랑 2 

파랑 3

>>>>>>>>>>>>>

빨강 (1, 0, 0)

노랑 (0, 1, 0)

파랑 (0, 0, 1)

 

y.head() / y_train[0] 등과 같이 y값을 살짝 찍어보면, onehot 인코딩 여부를 확인 할 수 있다.

 

onehot 인코딩 된 Y 값 onehot 인코딩 안 된 Y값
[0,0,0,1,0] 3
[0,1,0,0,0] 1
[0,0,0,0,1] 4
[1,0,0,0,0] 5

Onehot 인코딩 하는 방법

print(tf.one_hot(y_train[0], 10))

print(tf.one_hot(y_train[0], 10))

 

3. 선형 / 비선형 번갈아가면서 사용하기

Dense 선형

Relu 비선형

 

tf.keras.layers.Dense(512)

tf.keras.layers.Relu(512)

 

tf.keras.layers.Dense(512, activation = 'relu') 와 같이 표현 가능

def relu(x):
    return np.maximum(x, 0)
    
x = np.linspace(-10, 10)
y = relu(x)

plt.figure(figsize=(10, 7))
plt.plot(x, y)
plt.title('ReLU activation function')
plt.show()

 

4. 마지막 Dense

분류해야할 클래스의 갯수와 맞춰서 써주기

tf.keras.layers.Dense(1, activation = 'sigmoid')

tf.keras.layers.Dense(10, activation= 'softmax')

 

 

5. 컴파일 주의사항

softmax => loss = 'sparse_categorical_crossentropy')

sigmoid => loss = 'binary_crossentropy'

 

***********************************************************************

이진분류 : 둘 중 하나 (ex) 개 / 고양이, 나비 / 벌 )

방법1)

Dense(1, activation = 'sigmoid')

loss = 'binary_crossentropy'

sigmoid 함수는 x에 어떤 값을 넣든지 y는 0과 1 사이의 값이 나온다.

이 함수가 이진 분류에서 사용된다면, y값이 0.5 를 기준으로 개/고양이 분류를 한다.

def sigmoid(z):
    return  1/(1+np.exp(-z))

plt.figure(figsize=(10, 7))

x = np.arange(-10, 10)
y = sigmoid(x)

plt.plot(x, y)
plt.show()

 

방법2)

Dense(2, activation = 'softmax')

loss = 'categorical_crossentropy' (y값이 onehot 인코딩 되어있을 때)

또는

loss = 'sparse_categorical_crossentropy' (y값이 onehot 인코딩 안되어 있을 때)

각각의 뉴런이 될 확률을 구해서 가장 큰 값을 가진 뉴런으로 분류

A가 될 확률 : 0.7 

B가 될 확률 : 0.2

C가 될 확률 : 0.1

 

--> A로 분류

import numpy as np

a = np.random.uniform(low=0.0, high=10.0, size=3)

def softmax(a) :
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

y = softmax(a)
print('Class 별 확률 값 출력')
print('===' * 10)
for i in range(3):
    print('Class {} 의 확률: {:.3f}'.format(i, y[i]))
print('===' * 10)
print('Class 별 확률 값의 합: {:.1f}'.format(y.sum()))

Flatten이란?

  • 고차원을 1D로 변환하여 Dense Layer에 전달해 주기 위하여 사용합니다.
  • 28 X 28 의 2D로 되어 있는 이미지를 784로 1D로 펼쳐 주는 작업입니다.

이미지는 2차원 데이터(2D)

2D데이터는 Dense Layer에 못들어간다. 

2차원 데이터를 1차원으로 변환해주어야 함

 

5. Model 만들기

model 정의 할 때 input_shape 잡는 법

input 으로 들어가는 x_train의 shape를 확인하면 된다. 해당 결과를 그대로 사용하면 된다 (28,28)

x_train[0].shape
model = Sequential([
    # Flatten으로 shape 펼치기
    Flatten(input_shape=(28, 28)),
    # Dense Layer
    Dense(1024, activation='relu'),
    Dense(512, activation='relu'),
    Dense(256, activation='relu'),
    Dense(128, activation='relu'),
    Dense(64, activation='relu'),
    # Classification을 위한 Softmax 
    Dense(10, activation='softmax'),
])

Dense 노드를 2의 제곱수로 잡는 이유? : GPU의 병렬처리를 할때 2의 제곱수가 좀 더 학습이 빠름

Dense 노드수가 줄어들게 쌓는 이유? : 논문 등에서 자주 사용되는 경향임. 가이드라인과 같은 역할. 상관없음.

 

 

6. Compile

metrics 에 accuracy 담기

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['acc'])

loss = 'categorical_crossentropy'(잘못된 loss 함수)를 사용한다면, accuracy가 안올라감, 학습이 안되는 것

 

7. ModelCheckpoint: 체크포인트 생성

val_loss 기준으로 epoch 마다 최적의 모델을 저장하기 위하여, ModelCheckpoint를 만듭니다.

  • checkpoint_path는 모델이 저장될 파일 명을 설정합니다.
  • ModelCheckpoint을 선언하고, 적절한 옵션 값을 지정합니다.
checkpoint_path = "my_checkpoint.ckpt"
checkpoint = ModelCheckpoint(filepath=checkpoint_path, 
                             save_weights_only=True, 
                             save_best_only=True, 
                             monitor='val_loss', 
                             verbose=1)

 

8. 학습

  1. validation_data를 반드시 지정합니다.
  2. epochs을 적절하게 지정합니다. : 
  3. callbacks에 바로 위에서 만든 checkpoint를 지정합니다.

epoch은 감소하다가 다시 늘어나는 지점까지 충분히 주어야한다.

 

history = model.fit(x_train, y_train,
                    validation_data=(x_valid, y_valid),
                    epochs=20,
                    callbacks=[checkpoint],
                   )

 

1. Dense Layer (Fully Connected Layer)

: 완전히 연결된 레이어

각각의 노드들이 완전히 연결되어있는 레이어 = Dense Layer = Fully Connected Layer = FC

 

ㅇ 그림에서 보이는 하나의 동그라미는 = 노드 = 뉴런 이라고 한다.

ㅇ 그림에서 각각의 layer 마다 노드의 개수가 다르다. hidden layer1의 Dense는 4 

ㅇ input layer로 데이터가 들어와서 output layer로 데이터가 나간다.

ㅇ input layer에서는 input_shape를 명시해 주어야한다.

ㅇ 분류문제의 경우) output layer에서는 분류 class의 개수와 output layer의 노드의 개수가 일치해야한다.

    ex) 빨강/노랑/파랑 분류 문제시 output layer의 노드수는 3개

 

 

2. 위 그림의 모델을 코드화 해본다면 다음과 같다

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential

xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0], dtype=float)

model = Sequential([
    Dense(3, input_shape=[1]),
    Dense(4),
    Dense(4),
    Dense(1),
])

 

3. 컴파일하기 (optimizer와 loss 반드시 지정)

optimizer : 알고리즘, 어떤 알고리즘을 사용하여서 오차를 줄여나갈 것인가?

               ex) sgd : Stochastic Gradient Descent

loss : 오차값

               ex) mse : mean squered error

model.compile(optimizer='sgd', loss='mse')

 

4. 학습하기

순서대로 input 데이터 / output 데이터 / 학습시킬 횟수 / 진행상황 안보여줌

model.fit(xs, ys, epochs=1200, verbose=0)

 

5. 예측하기

# output
# 16.000046
model.predict([10.0])

결과적으로 y=x+6 일차함수를 예측하는 모델이므로 10을 넣었을때 y값이 16으로 잘 나오는 것을 확인할 수 있다.

크롤링이란?

웹페이지에 있는 정보를 내가 원하는 것만 뽑아서 수집하는 것이다.

 

주로 크롤링으로 많이 하는 것들은 이미지 파일들이다. 

이번에는 파이썬을 사용하여 이미지를 크롤링하고, 크롤링한 이미지 파일들을 opencv를 이용해서 원하는 포맷으로 편집까지 해보려한다.

 

크롤링에 많이 사용하는 것들은 뷰티풀숲(Beautiful Soup) 이다.

하지만 정적인 콘텐츠가 아니고, 동적인 콘텐츠의 경우 실제로 웹 창이 열려야 이미지 소스들이 그제서야(?) 웹페이지에 다운이 되는 경우가 많이 있다.

 

그래서 셀레니움(Selenium)을 사용한다.

 

1. 필요한 모듈을 설치한다.

!pip install bs4
!pip install selenium
!pip install opencv-python

 

2. 필요한 모듈을 import 한다

from bs4 import BeautifulSoup
from selenium import webdriver
import requests
import urllib.request
import time
import os
import urllib
from PIL import Image
import cv2

 

3. 자동차의 이미지를 크롤링 할 예정이므로 cars라는 딕셔너리에 '검색어':'저장할폴더이름' 형식으로 key값과 value값을 정한다.

link라는 빈 리스트를 만든다. 이 리스트는 나중에 img 소스의 링크를 저장할 리스트이다.

cars = {'셀토스':'seltos2'}
link = []

 

4. 먼저 셀레니움으로 웹드라이버를 불러온다. 

크롬 웹드라이버를 사용했는데, 크롬웹드라이버를 본인의 크롬 버전에 맞게 exe 파일을 다운받아서 exe 드라이버가 다운받아져 있는 디렉토리 경로를 입력하면 된다.

처음으로 띄울 웹페이지의 url을 입력한다.

for key in cars:
    driver = webdriver.Chrome('D:\chromedriver_win32\chromedriver.exe')
    driver.get('https://naver.com')
    

 

5.  네이버 창의 우클릭을 하여 "검사" 를 클릭한다.

 

 

6. '검사' 클릭시 나오는 우측 창 상단에 '화살표'모양을 누르고 검색창에 가져다 대면 해당 검색창 소스의 이름을 알 수 있다. name = 'query' 라고 적혀있다. 이 이름을 알아 내야 한다.

 

 

7. 알아낸 이름을 driver.find_element_by_name() 안에 작성한다.

이 함수는 말 그대로 요소의 이름으로 찾기 라는 것이다. 검색창이 소스상에서 이름이 query이므로 검색창에 .send_keys라는 매소드로 초기에 설정한 cars의 key 값인 '셀토스'를 입력한다.

 

입력 후 검색 버튼을 눌러야하는데, 이를 실행하는 방법은 다음과 같다.

검색버튼을 동일하게 화살표 모양으로 눌러서 html 소스를 찾는다.

해당 소스위에서 우클릭을 한 후 'copy' -> 'Copy XPath'를 한 후 driver.find_element_by_xpath() 안에 붙여넣기를 한다.

이는 해당 요소를 xpath로 찾는 다는 뜻이다. 이후 .click이라는 메소드를 하용하여 검색버튼을 클릭하는 행위까지 추가한다.

    driver.find_element_by_name('query').send_keys(key)
    driver.find_element_by_xpath('//*[@id="search_btn"]').click()
 

 

8. 여기서 조금 삽질? 까다로운 것이 나온다. 자동차 명에 따라서 어떤거는 상단에 바로 네이버 자동차 검색 페이지로 연결되는 것이 나오지만, 지금의 경우처럼 상단에 광고 링크나 파워링크가 먼저 떠서 네이버자동차검색 페이지 연결 링크가 아래로 내려가는 경우가 있다.

이는 어쩔 수 없지만 케이스에 따라 xpath를 바꿔주어야 한다.

대부분 맨 위의 상단의 div[2]값을 가져오는 듯 하지만, div[3] 값을 가져와야하는 경우도 있다.

    driver.find_element_by_xpath('//*[@id="main_pack"]/div[2]/div/div[2]/div/div[1]/dl/dt[1]/a').click()    
#     driver.find_element_by_xpath('//*[@id="main_pack"]/div[3]/div/div[2]/div/div[1]/dl/dt[1]/a').click()

 

 

9. 네이버 자동차 검색 링크를 클릭하면, 새로운 탭이 생성되므로 driver.swith_to.window로 탭을 변경해주어야 한다.

네이버 자동차 검색 링크에서 이미지 탭으로 이동한 후 time.sleep(1)로 1초 정도 이미지가 다운될 시간을 준다.(이는 생략 가능하지만, 생략할 경우 이미지가 다운 되기 전에 이미지 소스를 가져오려고 하여 도중에 에러가 나는 경우가 발생 할 수도 있다.)

img 라는 변수에 img 태그를 담고 get_attribute로 소스만 가져온다. 즉 해당 이미지가 가지고있는 인터넷 상에서 주소(url)만을 가져온다. 

그 url을 초기에 만들어둔 빈 리스트인 link에 담는다.

    driver.switch_to.window(driver.window_handles[1])
    driver.find_element_by_xpath('//*[@id="content"]/div[1]/ul/li[3]/a').click()
    time.sleep(1)
    img = driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/div/ul/li[2]/img')
    img.get_attribute('src')
    link.append(img.get_attribute('src'))

 

10. 최초 이미지는 위의 코드에서 저장을 했고, 그 이후에 더 많은 이미지를 진행하고 싶다면 for문으로 한장씩 옆으로 넘기면서 img 소스를 link라는 리스트에 저장을 하면 된다.

	for i in range(19):
        driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/a[2]/div').click()
        time.sleep(1)
        img = driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/div/ul/li[2]/img')
        img.get_attribute('src')
        link.append(img.get_attribute('src'))

 

11.  드라이버를 닫고, os 모듈을 통해 폴더를 생성한다. 초기에 지정한 cars[key] 의 value값으로 폴더를 만든다.

count 값은 폴더 안에서 이름을 지정할 때 중복이 되지 않게 하기위해 count를 하나씩 증하했다.

area = (0,0,980,570) 으로 지정하여 image를 원하는 크기로 자른 후 저장한다.

 	driver.close()
    count = 0
    os.makedirs(os.path.join('D:/blog/'+cars[key]))
    
    for url in link:
        count += 1
        urllib.request.urlretrieve(url, 'D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')
        image = Image.open('D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')
        area = (0,0,980,570)
        crop_image = image.crop(area)
        crop_image.save('D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')

 

12.  저장한 이미지를 2개씩 붙이고 border(테두리)를 만들어주는 코드이다.

    for i in range(1,22, 2):
        img1 = cv2.imread('D:/blog/'+cars[key]+'/asigd'+str(i)+'iwjed.jpg')
        img2 = cv2.imread('D:/blog/'+cars[key]+'/asigd'+str(1+i)+'iwjed.jpg')
        addv = cv2.vconcat([img1, img2])
        bordersize = 2
        border = cv2.copyMakeBorder(addv, top=bordersize, bottom=bordersize, left=bordersize, right=bordersize, borderType=cv2.BORDER_CONSTANT, value=[0,0,0])
        cv2.imwrite('D:/blog/'+cars[key]+'/asigd'+str(i*123)+'iwjed.jpg', border)
    
    

 

 

전체 코드 참조

cars = {'셀토스':'seltos2'}
link = []

for key in cars:
    driver = webdriver.Chrome('D:\chromedriver_win32\chromedriver.exe')
    driver.get('https://naver.com')
    
    driver.find_element_by_name('query').send_keys(key)
    driver.find_element_by_xpath('//*[@id="search_btn"]').click()
    
    driver.find_element_by_xpath('//*[@id="main_pack"]/div[2]/div/div[2]/div/div[1]/dl/dt[1]/a').click()    
#     driver.find_element_by_xpath('//*[@id="main_pack"]/div[3]/div/div[2]/div/div[1]/dl/dt[1]/a').click()
#     driver.find_element_by_xpath('//*[@id="main_pack"]/div[2]/div/div[2]/div/div[1]/dl/dt[1]/a').click()
    
    
    driver.switch_to.window(driver.window_handles[1])
    driver.find_element_by_xpath('//*[@id="content"]/div[1]/ul/li[3]/a').click()
    time.sleep(1)
    img = driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/div/ul/li[2]/img')
    img.get_attribute('src')
    link.append(img.get_attribute('src'))
    
    for i in range(19):
        driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/a[2]/div').click()
        time.sleep(1)
        img = driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/div/ul/li[2]/img')
        img.get_attribute('src')
        link.append(img.get_attribute('src'))
#         driver.find_element_by_xpath('//*[@id="container"]/div[5]/div/a[2]/div').click()
    
    driver.close()
    count = 0
    os.makedirs(os.path.join('D:/blog/'+cars[key]))
    
    for url in link:
        count += 1
        urllib.request.urlretrieve(url, 'D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')
        image = Image.open('D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')
        area = (0,0,980,570)
        crop_image = image.crop(area)
        crop_image.save('D:/blog/'+cars[key]+'/asigd'+str(count)+'iwjed.jpg')
    
    for i in range(1,22, 2):
        img1 = cv2.imread('D:/blog/'+cars[key]+'/asigd'+str(i)+'iwjed.jpg')
        img2 = cv2.imread('D:/blog/'+cars[key]+'/asigd'+str(1+i)+'iwjed.jpg')
        addv = cv2.vconcat([img1, img2])
        bordersize = 2
        border = cv2.copyMakeBorder(addv, top=bordersize, bottom=bordersize, left=bordersize, right=bordersize, borderType=cv2.BORDER_CONSTANT, value=[0,0,0])
        cv2.imwrite('D:/blog/'+cars[key]+'/asigd'+str(i*123)+'iwjed.jpg', border)
    
    

 

 

전체 코드 github에서 다운받기

github.com/eugenekk/crawling_naver_img.git

+ Recent posts