레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시
레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시

VS Code에서 py torch, jupyter notebook 설정 해보기

일단 나는 개발 환경으로 Visual Studio Code를 사용하고 있고,
Python은 Anaconda를 통해서 관리하고 있다.

최근 PyTorch를 설치하면서 jupyter notebook으로 학습하려하니, 약간의 삽질이 필요했으니 그 내용을 기록해보겠다.

1. PyTorch 설치

 매우 친절하게도 pytorch.org에 접속해보면 설치 환경에 따라 어떤 커맨드를 넣어야 하는지 나온다. 매우 친절하다. 일단 기분이 좋아졌다.
 물론 설치를 그냥 base환경에 하면 안되고, conda prompt에서 다음을 실행하고 한다.



 $ conda create --name ai_torch
 $ conda activate a_torch

여기서 'ai_torch'는 그냥 내가 정한 이름이니 아무거나 쓰면 된다.
 VS Code를 열면 해당 환경이 다시 로드되므로 앞으로 이 환경을 쓸 수있다.(물론 이미 python plug-in이 있다는 가정 하에...)

2. 가상 환경에 Jupyter notebook 설치

 Conda prompt에서 다음 커맨드로 jupyter notebook을 설치한다.



 $ conda install jupyter notebook 

 그럼 ipython이나 그 외 필요한 패키지 등이 설치된다.

 다 설치가 되었으면, 이 가상 환경의 커널(python 등의 실행 환경)을 등록해주자.
 등록을 해 놓으면 jupyter notebook에서 가상 환경을 선택해 사용 가능하다.


 $ python -m ipykernel install --user --name py_torch --display-name "[Py Torch]" 

 display-name 옵션 뒤의 내용은 알아서 정하자.

 이제 VS Code든 어디든 jupyter notebook에서 가상 환경을 사용할 수 있다.

Uncopyable class와 clone 함수

   C++의 경우 class를 생성하면 기본적으로 default constructor와 copy constructor, 대입 연산자가 기본으로 만들어진다. 이 세가지는 프로그래머가 작성하지 않더라도 컴파일러가 알아서 마치 사람이라면 밥 먹고 화장실 가듯이 자연스럽게 만들어 버린다.

   C++의 가장 어려운 점이자, OOP(Object Oriented Programming)이라면 어느 언어든 가지고 있는 문제는 객채의 state 관리이다. Class도 하나의 type으로 보므로 각종 사칙 연산의 overloading이 가능한데다, 구조 안에 다양한 class의 객체를 state variable로 가질 수 있어 까딱 잘못하단 지옥문이 열린다. 특히 멀티 쓰레드 환경에선 더 심하다.(덕분에 Functional Programming 추종자들에게 대차게 까이지만, FP도 VM은 C++로 만든게 많다. -_-)

   이런 고통을 조금이나마 완화할 수 있는 방법은, class 자체의 복사를 막아버리는 것이다.  물론 다 막으라는 것이 아니라, 한 클래스의 각각의 객체가 서로 독립적인 상태를 가져야 한다든가, copy는 허용하고 싶은데 내용물에 pointer가 있다던가 하는 경우에 고려할만하다. 특히 후자의 pointer를 내용물로 가졌을 때는 앞에 소개할 방법을 심각하게 고려해봐야 한다.

   다음과 같은 코드를 실행해보자.


class B 
{
public:
    B(int i)
    {
        k = new int;
        (*k) = i;
    }

    int val()
    {
        return *k;
    }

    int* valp()
    {
        return k;
    }
private:
    int *k;

};

...
B b(1);
B b3 = b;

std::cout  << "b : "  << b.valp()  << std::endl;
std::cout  << "b3 : " << b3.valp()   << std::endl; 

   이 코드를 실행하면 다음과 같은 결과를 얻을 수 있다.


 b : 0047AD50
b3 : 0047AD50

   즉, 같은 위치의 메모리 영역을 가리키게 되고, 한 객체에서 메모리 영역 내의 값을 바꾸면 다른 객채까지 영향을 준다.


   이런 문제를 해결하기 위해서는 일단 class의 기본적인 복사를 막는다. 다음과 같이 Uncopyable이라는 클래스를 선언하고 copy constructor와 대입연산자를 private으로 선언한다.


class Uncopyable
{
public:
    Uncopyable() {}
    ~Uncopyable() {}

private:
    Uncopyable(const Uncopyable&);
    Uncopyable& operator=(const Uncopyable&);
};



    그리고 다음 처럼 위의 클래스를 상속한 클래스를 만들어주자.
 class A : private Uncopyable
{
public:
    A(int i)
    {
        k = i;
    }

    int val() 
    {
        return k;
    }
private:
    int k;

};

A a(1);
A a2 = a; 


    위의 코드를 컴파일하면 Uncopyable 클래스에 대한 access violation이 일어나면서 컴파일이 되지 않는다. 그리고 베이스 클래스에 가상 함수로 clone이라는 것을 지정하여 하위 클래스가 clone을 구현하도록 하면 내가 원하는 방식으로 객체 복사를 할 수 있다.
 
class Base 
{
public:
   ...
   virtual Base* clone() = 0;
}


   개인적으로도 이 방식을 잘 활용하는데, 아직까지는 꽤 성공적인 듯 하다.

인생논어 - 1

  0. 조형권님이 쓴 <<인생논어>> 를 읽고 필사한다는 생각으로 구문들을 옮겨 적으려 한다.  1. 나만의 속도를 유지하라.   子曰, 射不主皮 爲力不同科 古之道也 (자왈, 사부주피 위력부동과 고지도야)  해석: 활을 쏠 때 ...