이하 글은 Tensorflow-models 모델 로딩을 위해 공부하고 문제를 해결한 글입니다.

모델 버전 관리 - 1. model-loading 글 보러 가기 

2023.11.30 - [AI/TensorFlow | Tensorflow.js] - [Tensorflow-models] 모델 버전 관리 - 1. model loading

 


 

문제 인식

  • npm install 
    • npm install @tensorflow/tfjs npm install @tensorflow/tfjs-converter npm install @tensorflow/tfjs-core npm install @tensorflow-models/hand-pose-detection 등을 실행하여 npm 모듈을 설치할 때, peer dependency 충돌이 있으면 다음과 같은 오류가 발생함.
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: @tensorflow-models/mobilenet@2.0.4
npm ERR! Found: @tensorflow/tfjs-converter@4.10.0
npm ERR! node_modules/@tensorflow/tfjs-converter
npm ERR!   peer @tensorflow/tfjs-converter@"^4.9.0" from @tensorflow-models/hand-pose-detection@2.0.1
npm ERR!   node_modules/@tensorflow-models/hand-pose-detection
npm ERR!     @tensorflow-models/hand-pose-detection@"^2.0.1" from the root project
npm ERR!   @tensorflow/tfjs-converter@"4.10.0" from @tensorflow/tfjs@4.10.0
npm ERR!   node_modules/@tensorflow/tfjs
npm ERR!     @tensorflow/tfjs@"^4.10.0" from the root project
npm ERR!   2 more (the root project, @tensorflow-models/face-detection)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @tensorflow/tfjs-converter@"~1.2.1" from @tensorflow-models/mobilenet@2.0.4
npm ERR! node_modules/@tensorflow-models/mobilenet
npm ERR!   @tensorflow-models/mobilenet@"2.0.4" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: @tensorflow/tfjs-converter@1.2.11
npm ERR! node_modules/@tensorflow/tfjs-converter
npm ERR!   peer @tensorflow/tfjs-converter@"~1.2.1" from @tensorflow-models/mobilenet@2.0.4
npm ERR!   node_modules/@tensorflow-models/mobilenet
npm ERR!     @tensorflow-models/mobilenet@"2.0.4" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

 

  • npm 모듈 사용(실행)
    • 특정 모델을 로딩하여 예측 시도할 때 (코드 실행할 때), peer dependency 충돌이 있으면 다음과 같은 오류가 발생하기도 함
    • 그러나 오류 양상이 다양하므로 밑 종류 하나 만으로 한정할 수 없음
    • 따라서 ‘~찾을 수 없음’, ‘resolve 하다가 ~없어서 문제 발생함’ 등의 뉘앙스의 오류는 peer dependency로 인한 오류가 아닐까? 의심해야 함
client:159 ./node_modules/scratch-vm/node_modules/@tensorflow/tfjs-converter/dist/tf-converter.esm.js
Module build failed: Error: ENOENT: no such file or directory, open 'C:\Workspace\Rogic\scratch-gui\node_modules\scratch-vm\node_modules@tensorflow\tfjs-converter\dist\tf-converter.esm.js'

 

  • 주의할 점은 npm install 할 때를 제외하고, peer dependency로 인한 오류임에도 콘솔에서 직접적으로 알려주지 않는다는 것
    • 따라서 두번째 느낌으로 발생한 오류는 궁극적으로 peer dependency로 발생하는 오류일 수 있음을 인지해야 함
    • 여타 오류 해결 방법을 사용하기 전, 후에 peer dependency로 인한 오류가 아닐까? 의심해야 함

 


 

충돌 원인 : 실제 설치된 패키지 버전 ≠ peer dependency에서 요구하는 패키지 버전

  • peer dependency 의미
    • 친구 패키지 명 + 버전
    • 친구 패키지 : 해당 패키지를 정상적으로 활용하기 위해 필요한 다른 패키지
    • 즉 실제로 패키지에서 직접 require(import) 하지는 않더라도 호환성이 필요한 경우 명시하는 것
    • npm 3 버전까지는 peer dependency를 자동으로 설치해줌, 4 - 6 버전에서는 경고 메시지만 띄워줌, 7 버전부터는 peer dependency 버전이 맞지 않으면 설치 불가
      → 나의 npm - -version : 9.6.4 , 그렇다면 실제 설치된 버전 ≠ peer dependency 요구 버전이라면 해당 패키지 아예 설치 및 실행 불가? NO!
      → 해결법은 맨 마지막에!

 

  • peer dependency 확인
    • package-lock.json
"node_modules/@tensorflow-models/hand-pose-detection": {
    "version": "2.0.1",
    "resolved": "https://registry.npmjs.org/@tensorflow-models/hand-pose-detection/-/hand-pose-detection-2.0.1.tgz",
    "integrity": "sha512-zRA+jz2qOq5FMcyqSFxaQyi6T4YNbMbQhd6SQMI791FQ8yYj23kLgYa73g2NssR5AmM/2ATu9Vcjnf7LUrVLOQ==",
    "dependencies": {
        "rimraf": "^3.0.2",
        "tslib": "^2.6.1"
    },
    "peerDependencies": {
        "@mediapipe/hands": "~0.4.0",
        "@tensorflow/tfjs-backend-webgl": "^4.9.0",
        "@tensorflow/tfjs-converter": "^4.9.0",
        "@tensorflow/tfjs-core": "^4.9.0"
    }
  },
  • dependency vs dev dependency
    1. dependency
      • 앱에 종속된 가장 일반적인 종속성
      • 런타임빌드타임개발중 일 때 모두 필요
      • 따라서 앱이 빌드될 때 여기에 속해 있는 패키지들이 모두 번들에 포함되어 배포
    2. dev dependency
      • 빌드타임개발중 일 때 필요
      • 따라서 앱이 빌드될 때 도움 주거나 참조 되지만, 번들에 포함X

 


 

해결법 (요약)

  • npm 7 버전부터는 peer dependency 버전이 맞지 않으면 설치 불가
    • 그러나 무조건 peer dependency에서 얘기하는 딱! 그! 버전만 설치해야 패키지 실행할 수 있다는 것은 말이 안 됨 (사용자마다 프로젝트, pc 상황이 다를 수 있기 때문)
    • 해결 방법은 npm 공식 깃헙 블로그 기준 2가지가 있음 : --force 또는 --legacy-peer-deps
    • 더보기
      You have the option to retry with --force to bypass the conflict or --legacy-peer-deps command to ignore peer dependencies entirely (this behavior is similar to versions 4-6). - in npm github blog
  • 2가지 방법 요약
    --force --legacy-peer-deps
    충돌 우회 충돌 무시
    package-lock.json에 몇 가지의 다른 의존 버전들을 추가 peerDependency가 맞지 않아도 일단 설치
    • 이번 프로젝트에서는 주로 --legacy-peer-deps 를 활용하여 peer dependency 충돌 해결 (사수 제안)
    • 그러나 일반적인 경우 --force--legacy-peer-deps 로 적용해보는 것이 좋을 것 같음
      ( ∵ --force--legacy-peer-deps 보다 덜 강제적)

 


 

이번 프로젝트 (Tensorflow-models 구현) 에서 주의할 점

  • peer dependency를 설치한 경우, 해당 패키지가 실제 실행 가능한지 빌드 + 실행해서 확인 필수
    • 실행해보아야 하는 것 : ①모델 로딩(create detector) ②예측(estimateHands)
  • 해당 프로젝트의 경우 다음과 같은 버전 특징을 갖고 있었음
      hand-pose-detection face-landmarks-detection pose-detection
    peer dependency 권장 버전 "peerDependencies":
    { "@mediapipe/hands": "~0.4.0", "@tensorflow/tfjs-backend-webgl": "^4.9.0", "@tensorflow/tfjs-converter": "^4.9.0", "@tensorflow/tfjs-core": "^4.9.0" }
    "peerDependencies":
    { "@mediapipe/face_detection": "~0.4.0", "@tensorflow/tfjs-backend-webgl": "^4.4.0", "@tensorflow/tfjs-converter": "^4.4.0", "@tensorflow/tfjs-core": "^4.4.0" }
    "peerDependencies":
    { "@mediapipe/pose": "~0.5.0", "@tensorflow/tfjs-backend-wasm": "^4.10.0", "@tensorflow/tfjs-backend-webgl": "^4.10.0", "@tensorflow/tfjs-backend-webgpu": "^4.10.0", "@tensorflow/tfjs-converter": "^4.10.0", "@tensorflow/tfjs-core": "^4.10.0" }
    실제 실행 가능한 최소 버전 ( hand-pose-detection, face-landmarks-detection, pose-detection 최신 버전 기준) - tfjs, tfjs-core, tfjs-converter : ^3.3.0 - tfjs, tfjs-core, tfjs-converter : ^3.3.0 - tfjs, tfjs-core, tfjs-converter : ^4.4.0
    • 위처럼 ①모델마다 실제 실행 가능한 최소 버전 및 권장 peer dependency 버전이 상이하고 ②향후 프로젝트 확장 가능성 고려하여 , 사수님 제안으로 tfjs, tfjs-core, tfjs-converter 모델 모두 4.10.0 으로 설치함
    • tfjs, tfjs-core, tfjs-converter 모델은 2점대 이후로 버전이 한 몸으로 움직임. 따라서 버전업 할 때도 한 번에 했음
    • 위 3개 모델을 제외한 나머지 모델 ( ex. @tensorflow/tfjs-backend-webgl @tensorflow/tfjs-backend-wasm @tensorflow/tfjs-backend-webgpu) 은 위 3개 모델을 설치하면 자동 실행되므로 별도 설치 필요 없음
      ( 사실 @tensorflow/tfjs-converter 도 4점대 이후에는 포함되어있지만 그 전에는 포함되어 있지 않으므로, 보수적으로 별도 설치함)

 

merry가 참고하여 구현한 Tensorflow-models 공식 깃헙 바로가기

이하 모든 내용의 근본 출처는 위의 공식 깃헙임을 밝힙니다.

 


 

문제 인식

  • model loading이 되지 않았음. 
  • 내가 구현 시도한 hand-ppse-detection 모델은 model loading에 해당하는 것이 createDetector 함수인데, 이하에서 설명할 해결하기 위한 노력을 모두 해보아도 밑 오류로 귀결되었음.
  • 이번 글의 문제는 시리즈 2편에서 작성할 peer dependency 까지 모두 이해해야 해결 가능함. 
detector-handpose.js:179 Error in animate: Error: Weight StatefulPartitionedCall/model/conv_handedness/MatMul/ReadVariableOp has unknown quantization dtype float16. 
Supported quantization dtypes are: 'uint8' and 'uint16'.

 


 

1.  createDetector() 함수 구조

export async function createDetector(
    model: SupportedModels,
    modelConfig?: MediaPipeHandsMediaPipeModelConfig | MediaPipeHandsTfjsModelConfig)  // createDetector() 함수의 옵션
  • hand-pose-detection이 아닌 face-landmarks-detection과 pose-detection도 모델 로딩 함수 구조는 거의 동일함
  • createDetector() 함수의 옵션
// MediaPipeHandsTfjsModelConfig
/* `detectorModelUrl`: Optional. An optional string that specifies custom url of
* the detector model. This is useful for area/countries that don't have access
* to the model hosted on tf.hub.
*
* `landmarkModelUrl`: Optional. An optional string that specifies custom url of
* the landmark model. This is useful for area/countries that don't have access
* to the model hosted on tf.hub.
*/

export interface MediaPipeHandsTfjsModelConfig extends MediaPipeHandsModelConfig {
    runtime: 'tfjs';
    detectorModelUrl?: string;
    landmarkModelUrl?: string;
}


// MediaPipeHandsMediaPipeModelConfig
export interface MediaPipeHandsMediaPipeModelConfig extends MediaPipeHandsModelConfig {
      runtime: 'mediapipe';
      solutionPath?: string;
}
  • 이번 프로젝트 특성 상 온라인 환경이 아니어도 (인터넷이 끊어져도) 기능이 정상적으로 작동되어야 했음. 
  • 따라서 tensorflow-hub (최근 kaggle로 이관되었음) 에서 모델을 다운로드 받았음 
  • 그래서 위 옵션들 중 detectorModelUrl, landmarkModelUrl 을 실제 모델이 저장된 위치로 올바르게 설정해야 했음.
  • 그러나 아무리 설정해도 문제 인식에서 제시한 오류만 출력됨

 


 

2. 해결하기 위한 노력

 

1) 오프라인으로 다운로드 받은 모델 구조 파악
  • 전체 모델 구조 = detector + landmark
  • 각 detector, landmark 구조 = json + binary 파일
    1. json
      • 모델의 '구조' 해당하는 부분
      • 모델의 각 레이어에 대한 정보와 레이어가 어떻게 연결되어 있는지에 대한 정보
        →  이 때 레이어는 CNN의 그 layer임
      • 모델의 아키텍처의 모든 정보를 제공 → 이 파일만으로 모델의 구조를 재구성 가능
      • model.json의 weightsManifest 에서 바이너리 파일을 자동 참조
        → 따라서 바이너리 파일을 model.json과 동일한 디렉토리에 저장해놓는다면, 수동으로 경로를 지정할 필요 없음
      •  
      • 더보기
        "weightsManifest": [{"paths": ["group1-shard1of1.bin"],
    2. binary
      • 모델의 '가중치' 에 해당하는 부분 
      • 학습된 파라미터 포함 (ex. 각 레이어의 가중치와 편향 값 등)
      • 모델의 학습 결과를 저장하는 데 사용
      • 따라서 이 파일이 있어야만 학습된 모델을 이용하여 새로운 데이터 예측을 수행 가능
  • 오프라인으로 모델 다운 받은 모습

01

 


 

2) detector, landmark 파일을 각각 Url 옵션에 넣으면 된다고 생각했음
  • 그러나 어떠한 String 형식으로 넣어야 하는지 의문
  • 해결법
    • 힌트 : detectorModelUrl, landmarkModelUrl에 특정 경로를 쓰면, localhost:포트번호/ ~ 이하 경로에서 파일을 찾음
    • 따라서 GUI(빌드 시작점)에서 VM에 저장된 tensorflow-models를 찾을 수 있도록 경로를 작성해주어야 함
      → 이 경로는 webpack.config.js 에 저장되어 있음. 만약 아래 구조로 저장되어있지 않다면 내가 직접 설정해야 함
    • 이하 예시처럼 설정되어 있다면 해결법 내의 Url 설정한 것처럼 설정하여 VM에 저장된 tensorflow-models 파일들에 접근 가능함
plugins: base.plugins.concat([
	new CopyWebpackPlugin({
    patterns: [
			{
        from: 'node_modules/scratch-vm/tensorflow-models',
        to: 'static/tensorflow-models'
    },

 


 

3) model.json과 binary 파일 위치를 url 구조로 바꾸어주는 코드 사용해보기
  • 2) 실행했는데 계속 문제 인식에서 언급한 quantization 오류 발생함 
  • 따라서 이하 제시한 model.json과 binary 파일 위치를 url 구조로 바꾸어주는 코드 사용하기도 했었음
  • 물론 정상적으로 모델 로딩하지 못 하여 문제 인식에서 언급한 quantization 오류 또 발생함 
_bindPage () {
    return new Promise((resolve, reject) => {
        this.knn = knnClassifier.create();
        tf.ready().then(() => {
            // 바이너리 파일을 읽어와 blob -> url중 필요한 값 추출
            let blobList = [];
            const binaryLength = 4
            for (let i = 1; i <= binaryLength; i++) {
                const binary = require(`!!url-loader!./mobilenet-model/group1-shard${i}of${binaryLength}.bin`);
                const blob = this._b64toBlob(binary.default.slice(binary.default.indexOf('base64,') + 7))
                const url = URL.createObjectURL(blob)
                const urlArr = url.split("/");
                blobList.push(urlArr[urlArr.length - 1]);
            }

            // json data를 읽어와서 바이너리 파일 url을 이용한 paths 값 수정
            const modelJson = require('./mobilenet-model/model.json');
            modelJson.weightsManifest[0].paths = blobList;

            const blob = new Blob([JSON.stringify(modelJson)]);
            mobilenetModule.load({
                version: 1,
                alpha: 1.00,
                modelUrl: URL.createObjectURL(blob)
            }).then(module => {
                this.mobilenet = module;
                resolve();
            }).catch(err => {
                this.mobilenet = null;
                this.knn = null;
                console.warn(err)
                reject(err);
            });
        });
    });
}

_b64toBlob (b64Data, contentType = '', sliceSize = 512) {
    const byteCharacters = atob(b64Data);
    const byteArrays = [];

    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize);

        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }

    const blob = new Blob(byteArrays, {type: contentType});
    return blob;
}

 


 

해결법 (요약)

  • 이하 2가지가 모두 충족되어야 정상적으로 모델 로딩 (createDetector()) 할 수 있음 
    1. 모델 버전 설정 : hand-pose-detection은 최신 버전 + tfjs는 peer dependency 충돌나도 실제 실행은 되는 버전으로 버전업
      모델 버전 관리 - 2. peer dependency 충돌 글 보러 가기 
           
    2. 옵션 detectorModelUrl, landmarkModelUrl 설정
_createDetector() {
  const model = SupportedModels.MediaPipeHands;
  const detector = createDetector(model, {
      runtime: "tfjs",
      modelType: "lite",
      maxHands: 2, // or 2~10.
      flipHorizontal: false,
      staticImageMode: false,
      detectorModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_detector_lite_1/model.json",
      landmarkModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_landmark_lite_1/model.json",
  });
  return detector;
}

 

npm link 에 대한 개념은 이전 글에서 정리하여 생략하였습니다!

2023.10.17 - [Backend/Etc : Setting | Git] - [Setting] 내부 서버로부터 파일 clone | npm link | build

 


 

문제 인식

  • 1번째 작업 : GUI의 develop 브랜치(root)와 VM의 feature/tfjs-handpose 브랜치에서는 빌드 성공 + 내가 작성한 코드가 반영 잘 됨
  • 그러나 2번째 작업 : face-detection을 적용하기 위한 feature/tfjs-face 브랜치에서 작업 후, 다시 feature/tfjs-handpose로 돌아와 빌드하면 빌드 실패
  • 오류 내용
node:internal/modules/cjs/loader:1084 Uncaught Error: Cannot find module '@mediapipe/hands'
Require stack:
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\mediapipe\detector.js
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\create_detector.js
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\index.js
C:\Workspace\AI\Handpose\ai_roborobo\index.html at node:internal/modules/cjs/loader:1084:15 at Function._resolveFilename (node:electron/js2c/renderer_init:2:5527) at node:internal/modules/cjs/loader:929:27 at Function.<anonymous> (node:electron/js2c/asar_bundle:2:13327) at Function._load (node:electron/js2c/renderer_init:2:4757) at Module.require (node:internal/modules/cjs/loader:1150:19) at require (node:internal/modules/cjs/helpers:121:18) at Object.<anonymous> (C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\face-detection\dist\mediapipe\detector.js:56:21) at Object.<anonymous> (C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\face-detection\dist\mediapipe\detector.js:210:3) at Module._compile (node:internal/modules/cjs/loader:1271:14)
  • GUI에서 최종 빌드를 진행하기 때문에, 위 오류는 결국 GUI에서 @mediapipe/hands 모듈을 인식하지 못한다는 소리가 됨
  • GUI는 ①node_modules/@tensorflow-models 에서 hand-pose-detection 모델을 인식하고, ②node_modules/scratch-vm/~ 에서 VM과 관련된 코드를 인식함. 이 때 둘은 npm link로 이어져 있음
  • 그러나 나는 VM에 @mediapipe/hands 모듈을 설치해놓은 상태였음에도 GUI가 인식하지 못함
  • 따라서 npm link의 문제라고 생각함

 


 

1. npm link 의미(용도)

  • Symbolic link ( 줄여서 Symlink) = 바로가기 파일
  • GUI에서 npm link VM 을 실행하면, 외부 모듈(VM)이 현재 프로젝트(GUI)의 node_modules 디렉토리에 설치된 것처럼(npm install한 것처럼) 사용될 수 있게 해줌
  • 즉 해당 모듈(GUI)에 VM에 대한 전역 심볼릭 링크를 설정하는 것

 


 

2. npm link 사용법

  • 위 오류 해결 방법 후보
    1. 프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI의 develop 브랜치에 npm link
    2. 프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI에 브랜치 생성하여 npm link
  • 내 생각 1: GUI root 디렉토리를 계속 건드리는게 좋지 않아 보임, 따라서 후보2를 실행해보려고 함
  • 그러나 npm link는 브랜치 단위가 아닌 프로젝트 단위(디렉토리 단위)로 생성
    • 따라서 후보2를 실행해도 브랜치별로 다른 npm link가 걸리는 것이 아니라, 설정된 npm link가 계속 변경됨
    • 따라서 후보1 실행하기로 함
  • 핵심 코드
// blocks
npm link l10n

// l10n
npm link l10n

// VM
npm link l10n blocks --force  // peer dependency conflict 방지

// GUI
npm link l10n blocks VM
  • npm link를 프로젝트가 작은 것 → 큰 것 순서로 진행하는 느낌
  • --force 또는 --legacy-peer-deps 는 peer dependency conflict 를 방지하기 위해 실행 

 


 

해결법

프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI의 develop 브랜치에 npm link 하고 build

문제 인식

  • 나는 지금까지 항상 git commit -m “커밋 메시지”git push origin 브랜치명 을 모두 실행하여 내 코드를 공유했었음
  • 그래서 commit과 push의 의미를 구별하지 못 함, 왜 2가지 단어가 있는지 의문이었음. 따라서 나는 항상 ‘push 했다’ 라고 표현해왔음
  • 그러나 내가 하나의 프로젝트 작업을 완료하자, 사수께서 서버에 올려 달라고 하심
  • 나는 지금까지 commit, push만 있는줄 알았는데 또 무엇인가 해야 하나 고심하였음. 그러나 알고보니 작업한 코드를 서버에 올리는 것 = push 라는 것이었음
  • 따라서 양자의 차이를 알게 됨

 


 

1. commit과 push 의 차이점

  Commit  Push
명령어 git commit -m “커밋 메시지” git push origin 브랜치명
의미 로컬 저장소에 저장 원격 저장소에 저장 → 원격 저장소는 서버, 깃헙 등을 말함
과정 내가 작업하다가 끊고 싶을 때 마음대로 커밋하면 됨 PM의 허락 받고 푸시해야 함
Staging → Commit Staging → Commit → Push
   
브랜치 삭제로 알아보는 차이 git branch -d 브랜치명 git branch -D 브랜치명 (수정된 파일이 커밋되지 않아도 삭제) git push origin -d 브랜치명
  • origin : 저장소 명; 따라서 각 프로젝트에서 설정한 서버 저장소 명으로 origin 대신 설정 가능. 그러나 대부분 origin으로 설정되어 있음

문제 인식

      • 기능별로 브랜치를 만들어서 작업해야 한다고 하심 ( ex. handpose / face / pose | 각 경우에서 구체적으로 model / detect / draw )
        • 공통 사용할 npm 모듈 설치하여 feature/tfjs → 그 브랜치에서 feature/tfjs-handpose, feature/tfjs-face, feature/tfjs-pose로 뻗어나가기

브랜치 예시

  • 그러나 이미 작업 중인 파일이 있다면, 브랜치 생성하여 checkout 해도 계속 수정된 파일이 남아있다는 문제 + commit은 부담스러움
  • git stash를 사용하면 됨!

 


의미 (용도)

 

  • 임시 저장소
  • commit은 부담스럽고 checkout 해서 다른 브랜치에서 새로 작업하고 싶을 때, stash라는 임시 저장소에 저장하였다가 불러와서 사용하면 됨

 

사용법

  • stash 생성(임시 저장) : git stash (save)
    • save 적어도 되고 안 적어도 됨
    • 위 명령어 사용하여 stash 생성하고, 작업할 브랜치로 checkout 하면 됨
    • Node.js의 경우 package.json (내가 설치, 삭제한 npm 모듈 기록)까지 임시 저장됨
  • stash 저장 목록 확인 : git stash list
    • 임시 저장한 파일을 현재 내가 있는 브랜치로 불러오는 것임
    • stash 이름을 생략하면 가장 최근에 저장된 stash가 나옴 → LIFO: 후입선출, 스택의 자료 구조
  • stash 삭제: git stash drop (@stash{0})
    • stash 이름을 생략하면 가장 최근에 저장된 stash가 삭제됨

참고 문제 

while True:  # 무한 루프 돌겠다
    try:
        A, B, C = map(int, input().split())
        jumpA = B - A - 1
        jumpB = C - B - 1
        ans = max(jumpA, jumpB)
        if ans == 0:
            print(0)
        else:
            print(ans)
    except EOFError:  # input 공백일 때 읽어들이려고 할 때 발생하는 에러, break 처리
        break

참고 문제 

T = int(input())
C = []
for i in range(T):
    C = list(map(int, input().split()))
    
    # 값 초기화
    Q = D = N = P = 0
    
    # 리스트의 첫 번째 값만 활용하고 바로 답 출력
    Q = C[0] // 25
    D = C[0] % 25 // 10
    N = (C[0] % 25) % 10 // 5
    P = ((C[0] % 25) % 10) % 5 // 1
    print(Q, D, N, P)

개요

심볼릭 링크에 대해서는 '파이썬 2개 버전 동시 사용하기' 글에서 이미 다루었다. 해당 글을 작성하고 최근까지도 나는 이 경우에만 심볼릭 링크를 사용하는 줄 알았다. 그러나 자사 제품의 로컬 실행을 위해 빌드하며 다른 메시지의 오류 2개를 심볼릭 링크로 해결해보며, 이것이 다양한 경우에서 사용될 수 있음을 깨달았다. 요약하자면 심볼릭 링크는 파일 A와 B가 멀리 떨어진 위치에 있을 때, A 파일을 실행하며 종속적으로 B 파일 실행이 필요한 경우 A에 B 파일의 위치를 알려주는 느낌이다.

 


 

Windows에서의 Symbolic Link

Symbolic Link 란?
  • 링크를 연결하여 원본 파일을 직접 사용하는 것과 같은 효과를 내는 링크이다.
  • 윈도우의 바로가기와 비슷한 개념이다.
  • 특정 폴더에 링크를 걸어 NAS, library 원본 파일을 사용하기 위해 심볼릭 링크를 사용한다.
  • 소프트 링크라고도 한다.
  • 리눅스 용어이지만 자사에서는 윈도우로 개발하는 바, 이하에서는 윈도우 명령어와 오류로 설명한다. 

 

명령어 및 결과

1. 링크 생성

  • 파일에 대한 링크 생성 : mklink 생성파일 실행파일 
mklink C:\Workspace\Rogic\scratch-blocks\python.exe C:\Python27\python.exe
// cmd 결과
C:\Workspace\Rogic\scratch-blocks\python.exe <<===>> C:\Python27\python.exe에 대한 기호화된 링크를 만들었습니다.
// 파일탐색기 결과
심볼릭링크 유형으로 실행파일.exe가 추가됨

 

  • 디렉토리에 대한 링크 생성 : mklink 생성디렉토리 실행디렉토리
    -> 파일에서 디렉토리로만 변경되고, 로직 및 결과는 동일하게 확인 가능하다.

 

2. 링크 삭제 

  • 파일에 대한 링크 삭제 
    • cmd 창을 이용 : (생성파일이 있는 디렉토리로 이동하여) del 생성파일
    • 파일탐색기 이용 : 위 사진에 있는 심볼릭 링크 파일 삭제
  • 디렉토리에 대한 링크 삭제
    • cmd 창을 이용 : (생성 디렉토리로 이동하여) rmdir 생성디렉토리 
    • 파일탐색기 이용 : 상동

 


 

Trouble Shooting

오류 내용
  • scratch-blocks에서 npm run prepublish 실행 시 아래 오류 발생 
// 파이썬에서 site-packages를 찾을 수 없는 오류
ImportError: No module named site

// 자바가 path에 없다는 오류
Could not find "java" in your PATH.
Using remote compiler: closure-compiler.appspot.com ...

Error: Closure not found.

 

오류 원인(내 생각)
  • 파이썬의 경우 2개 버전을 함께 사용하므로 설치한 후부터 지금까지 경로가 꼬였을 수 있겠다고 생각했다. 따라서 완전 삭제 후 재설치하고 오류를 해결하기로 했다.
  • 그러나 재설치해도 위 오류는 동일하게 발생했다. 따라서 scratch-blocks에서 실행되는 파이썬(ver 2.7.18)에게 site-packages를 찾을 수 있도록 알려주어야 겠다고 생각했다. 
  • 자바의 경우에도 고급 시스템 설정-환경변수-Path에 올바른 경로를 추가해도 위와 같은 오류가 발생했다. 따라서 scratch-blocks에서 실행되는 자바가 어디 있는지 알려주어야 겠다고 생각했다. 
  • 즉 위의 두 문제 모두 메시지는 다르지만 '알려준다' 라는 요점이 같고, 이것이 곧 심볼릭 링크라고 생각했다!

 

해결 
// 파이썬은 두 버전의 명령어를 구분하여 심볼릭 링크 만들기
mklink C:\Workspace\Rogic\scratch-blocks\python.exe C:\Python27\python.exe  // 빌드 명령어 : python
C:\Workspace\Rogic\scratch-blocks\python.exe <<===>> C:\Python27\python.exe에 대한 기호화된 링크를 만들었습니다.

mklink C:\Workspace\Rogic\scratch-blocks\py.exe C:\Users\KHR\AppData\Local\Programs\Python\Python312\python.exe  // ai 개발 명령어 : py
C:\Workspace\Rogic\scratch-blocks\py.exe <<===>> C:\Users\KHR\AppData\Local\Programs\Python\Python312\python.exe에 대한 기호화된 링크를 만들었습니다.


// 자바
mklink "C:\Workspace\Rogic\scratch-blocks\java.exe" "C:\Program Files (x86)\Java\jre-1.8\bin\java.exe"
C:\Workspace\Rogic\scratch-blocks\java.exe <<===>> C:\Program Files (x86)\Java\jre-1.8\bin\java.exe에 대한 기호화된 링크를 만들었습니다.
  • 주의할 점
    • 빌드하는 디렉토리 위치에서 심볼릭링크를 생성해야한다! 처음 cmd 창을 열었을 때 설정 되어있는 기본 디렉토리에서 링크 생성해봤자 소용 없다!
    • cmd 창을 관리자 권한으로 열어야한다! 관리자 권한으로 열지 않으면 명령어가 권한이 없어 작동하지 않는다!

 


 

참고 자료

https://bluedrim.tistory.com/entry/%EC%9C%88%EB%8F%847-%EC%8B%AC%EB%B3%BC%EB%A6%AD-%EB%A7%81%ED%81%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%8F-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0

 

윈도7 심볼릭 링크 만들기 및 삭제하기

윈도7 심볼릭 링크 만들기 및 삭제하는 방법, 심볼릭 링크라고도 하고 소프트 링크라고도 함 먼저 command 창을 관리자 권한으로 실행시키는 것이 필요. 보조프로그램에서 "명령 프롬프트"를 마우

bluedrim.tistory.com

231031 7번째 완료

 

'Backend > Enviornment setting | Git' 카테고리의 다른 글

[Setting] Visual Studio Code 위주 유용한 단축키 + 확장 앱  (0) 2023.11.30
[Git] commit과 push  (0) 2023.11.30
[Git] git stash  (0) 2023.11.29

개요

회사에서 첫 번째 프로젝트를 받았다. 사실 이번 프로젝트는 개발보다는 패키지 응용, 자사 제품에 맞게 커스텀하는 것에 가깝기는 하다. 어쨌든 프로젝트 내용을 요약하자면 다음과 같다. 

AI 개발 : TensorFlow.js*의 hand-pose-detection 패키지를 이용하여 손가락 keypoints 예측
 * 보다 정확히 말하면 TensorFlow.js 의 tfjs-models 레포의 hand-pose-detection 패키지이다. 

사실 프로젝트 설명을 들었을 때 드는 감정은 '막막하다'였다. 차장님께서는 웹캠으로 손(가락)을 인식할 때마다 그 손가락의 좌표를 예측했으면 좋겠다고 하셨는데, 웹캠은 어떻게 연결되는건지, 손가락 좌표의 기준점은 어떻게 되어서 어떤 방식으로 계산되는건지, 그걸 전부 Node.js 서버로 어떻게 돌린다는 것인지 이해가 되지 않았다. (물론 내가 아직 handpose와 hand-pose-detection 패키지가 어떠한 방식으로 작동하는지 이해하지 못 한 탓도 있지만...) 이하부터는 내 삽질의 기록이다...

TensorFlow 란? -> https://merrykang.tistory.com/7
handpose vs hand-pose-detection 패키지 비교 -> https://merrykang.tistory.com/7

 


 

Npm을 이용하여 필요한 패키지 설치

 

실행 코드 및 고민의 흔적 
// 패키지 설치
// 아래와 같은 패키지에 대해 install, uninstall을 최소 100번 반복했음 
npm install @tensorflow-models/handpose (--legacy-peer-deps)
npm install @tensorflow/tfjs-core
npm install @tensorflow/tfjs-converter
npm install @tensorflow/tfjs
npm install @tensorflow/tfjs-node
npm install @tensorflow/tfjs-node-gpu

// Node.js 환경에서 파일 실행
// 해당 파일에는 require(node-gpu) 등의 코드가 적혀있어야함
node 파일경로/파일명.js

 

한계
  • node-cpu로 빌드까지는 성공 (명령어: node 실행파일명.js), 그러나 gpu 가동하지 못하는 문제
    • 이미지 프로세싱이므로 gpu 가동이 필수적이었다.
    • 그러나 CUDA 등 gpu 돌리는 데에 필요한 프로그램을 모두 설치해도 gpu 가동하지 못 했다. 
  • GPT 에 물어봐도 결국 버전 문제라는 답변
    • 즉, 위에서 적은 패키지와 peer 패키지의 버전이 호환되지 않는 문제가 발생했다.
    • 그러나 차장님은 빌드 되는데 나만 안 되는지 이해 불가, 모두 공통으로 빌드하고 있는 버전을 뒤로 하고 나만 다른 버전 사용할 수 없었다.
  • 파이썬 2.7 버전을 찾지 못하는 문제 
    • node.js 환경에서 gpu를 가동하려면 파이썬 2.7 버전을 이용해야한다.
    • 그러나 require(node-gpu) 한 채로 node 실행파일명.js로 파일을 실행하면 아래와 같은 오류가 반복적으로 발생했다.(내가 가장 많이 보았던 오류기도 함)
npm ERR! gyp ERR! find Python
npm ERR! gyp ERR! find Python Python is not set from command line or npm configuration
npm ERR! gyp ERR! find Python Python is not set from environment variable PYTHON
npm ERR! gyp ERR! find Python checking if "python3" can be used
npm ERR! gyp ERR! find Python - "python3" is not in PATH or produced an error
// ... 이런식으로 Python, python3 으로 명령어에 맞는 파이썬 프로그램을 찾지 못하는 문제

 

결론

위 오류가 계속 반복적으로 발생하고, 얘내들을 하루종일 붙잡고 있으면서 내 접근이 틀렸을 수도 있겠다고 생각했다. 따라서 ①연속적 이미지가 아닌 1개 이미지에 대해 좌표 예측을 시도하고 ②우선 html로 구현해야 겠다고 생각했다. 이러한 생각 하에 검색하던 도중 좋은 레퍼런스를 발견했다! https://da2so.tistory.com/44 다음 글에서는 1개 이미지 손 좌표를 예측하는 코드와 트러블 슈팅을 정리할 것이다.

 

TensorFlow.js (2) - WebGL 기반 hand pose detection

0. WebGL 기반 hand pose detection 오늘은 TensorFlow.js의 backend가 무엇이 있는 지 알아보고 사용가능한 backend 중 하나인 WebGL을 기반으로 hand pose detection을 해볼것입니다. hand pose detection만 하면 재미가 없

da2so.tistory.com

2023.10.30 8번째 글 완료!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

개요

회사에서 처음으로 프로젝트를 부여받았다. 손 이미지 좌표를 예측하는 AI를 개발하는 것이었고, 예측 과정은 다음과 같다. 

  1. 웹캠으로 손 영상이 들어옴
  2. 프레임 단위로 캡쳐된 이미지를 텐서* 형태로 변환
    * 텐서
     - 데이터가 3차 이상으로 들어있는 것; 3차원인 경우 x(row), y(column), z(depth)로 구성됨
     - 3차원 이상의 정보를 담을 수 있어 일반 테이블 구조보다 많은 정보를 담을 수 있음. 그러나 데이터 해석 시 데이터 구조에 대한 기초 지식이 요구됨
  3. 텐서 형태로 인식된 손의 좌표(x, y, z(깊이) 축)를 예측

위와 같은 과정을 수행하기 위해 차장님께 TensorflowHandpose, Handpose detection 라이브러리를 사용하면 된다고 전달받았다. 그러나  모르는 것 투성이었으므로 꼬리 문제 풀듯이 꼬리 개념으로 정리하고자 한다.

 


 

TensorFlow 란?

텐서플로(TensorFlow)는 구글(Google)에서 만든 데이터 흐름 프로그래밍을 위한 아파치 2.0 오픈소스 소프트웨어 라이브러리이다. 특히 머신러닝, 딥러닝 프로그램을 쉽게 구현할 수 있도록 해준다. 기본적으로 C++로 구현되어 있으며, Python, Java, Go 등 다양한 언어를 지원한다. 그러나 대부분의 편한 기능들이 Python 라이브러리로 구현되어 있어 언어로 개발하는 것이 편하다. 텐서플로의 라이브러리들은 깃헙에 정리 되어 있다. 이번 프로젝트를 수행하기 위해 나는 그중에서도 tfjs-models 라이브러리handpose, hand-pose-detection 패키지를 참고해야 했다. 그러나 각 패키지의 차이가 무엇인지, 둘 중 무엇을 더 중점적으로 사용해야 하는지 의문이 있었다.

 

Handpose 라이브러리 vs Handpose detection 패키지의 차이점
  Handpose Handpose detection
사용 예시  3D 손 부위 key points(landmarks) 감지를 위한 Media pipe hands 모델 구현  - Google's Real-time Hand pose Detection with Media pipe 모델 구현 
- TensorFlow Lite Micro Speech 예제에서 사용된 모델을 구현 
특징  - 손바닥, 손가락, 손목을 합친 21개의 key points 감지 
- 이미지 또는 비디오에서 손 추적 가능 
- 웹 어플리케이션에서 복잡한 3D key points 감지 기능이 필요한 경우 사용 
- 임베디드 시스템(마이크로 컨트롤러)에서 음성 명령과 함께 실시간으로 손 동작을 감지하는데에 사용하기 좋음

 

위와 같은 특징들로 인해 나는 프로젝트에서 Handpose 패키지를 중점적으로 사용하되, 웹캠 구현 등 기타  사항에서는 Handpose detection 패키지를 적극적으로 활용하기로 결정했다!

 


 

Human pose Estimation 이란?

현재 내가 하고 있는 프로젝트 내용, 텐서플로의 Handpose 및 Handpose detection 패키지는 모두 Human pose Estimation에 속한다.  이에 대한 이론적인 내용은 방대하므로 별도의 글에서 보다 구체적으로 정리하도록 하고, 이 글에서는 의미와 프로젝트와 관련된 내용만 간략하게 정리하고 넘어가고자 한다. 

 

의미

Human pose Estimation(& Tracking)은 Semantic key points*를 검출하고 ②key points 사이의 관련성을 찾고 ③지속적으로 추적하는 컴퓨터 비전**의 과제이다. 나는 Human pose Estimation 중에서도 첫 번째로 손 위치 추적에 대한 프로젝트를 부여받은 것이다. 명칭에서도 알 수 있듯 Human pose Estimation은 Pose Estimation의 한 종류이다. Pose Estimation(포즈 추정)은 컴퓨터 비전에서 유명한 과제 중 하나이다. 
  * Semantic key points : 의미 있는 점; 즉 사람 신체의 오른쪽 어깨, 왼쪽 무릎 등을 예로 들 수 있음
  **  컴퓨터 비전 (vision) : 사람의 시각을 모방하여 기계가 컴퓨터 영상을 처리할 수 있도록 도와줌

 

원리

대부분의 Pose Estimator는 2개 과정으로 위치를 추정한다. 

  • bounding box로 사람 또는 물체를 탐색한다.
  • 각 박스에서 탐색 대상의 key points를 찾아낸다. 사람의 경우 key points는 팔꿈치, 무릎, 손목 등이 될 수 있다. Single-pose estimation 의 경우 주어진 영상에서 하나의 물체의 pose를 추정하는 것이 목적이고, Multi-pose estimation의 경우 여러 물체를 탐지하는 것이 목적이 된다. 

 

Handpose 패키지를 이용한 AI 개발이 속하는 method의 범위

딥러닝의 빠른 발전으로 딥러닝 기반 Pose Estimation이 고전 방식에 비해 우월한 성능을 보이고 있으며 그 종류가 다양하다. 이번 프로젝트는 Node.js 기반 서버에서 동작하는 자사 제품에 추가될 기능이므로, 내 생각에는 Handpose 패키지를 이용한 프로젝트는 PoseNet 모델을 이용한 것이라고 볼 수 있을 것 같다. 

PoseNet
  - 경량으로 모바일 또는 웹 브라우저에서 작동하기 위한 모델 
  - TensorFlow.js 를 기반으로 구축된 사전 학습 모델

 

 


 

 

참고 자료

TensorFlow 란?

https://ko.wikipedia.org/wiki/%ED%85%90%EC%84%9C%ED%94%8C%EB%A1%9C

 

텐서플로 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 텐서플로(TensorFlow) 또는 텐서플로우는 다양한 작업에대해 데이터 흐름 프로그래밍을 위한 오픈소스 소프트웨어 라이브러리이다. 심볼릭 수학 라이브러리이자,

ko.wikipedia.org

https://excelsior-cjh.tistory.com/148

 

[러닝 텐서플로]Chap01 - 텐서플로 란?

Chap01 - 개요1.1 텐서플로 란? 텐서플로(TensorFlow)는 구글(Google)에서 만든, 딥러닝 프로그램을 쉽게 구현할 수 있도록 다양한 기능을 제공해주는 라이브러리다. 텐서플로 자체는 기본적으로 C++로 구

excelsior-cjh.tistory.com

 

Human pose Estimation 이란?

https://supermemi.tistory.com/entry/Human-Pose-Estimation-%EC%9D%B4%EB%9E%80-2022

 

Human Pose Estimation 이란? (2022)

Human Pose Estimation Ultimate Overview in 2022 Human Pose Estimation with Deep Learning - Ultimate Overview in 2022 - viso.ai Pose Estimation is a computer vision technique to predict and track the location of a person or object. List of use cases and arc

supermemi.tistory.com

https://viso.ai/deep-learning/pose-estimation-ultimate-overview/

 

Human Pose Estimation with Deep Learning - Ultimate Overview in 2023 - viso.ai

Pose Estimation is a computer vision technique to predict and track the location of a person or object. List of use cases and architectures.

viso.ai

 

+ Recent posts