<!-- 둘이 set-->
npm install @tensorflow-models/hand-pose-detection --legacy-peer-deps
npm install @mediapipe/hands --legacy-peer-deps
<!-- 위의 핵심 라이브러리를 실행할 수 있도록 하기 위한 peer dependency-->
npm install @tensorflow/tfjs --legacy-peer-deps
npm install @tensorflow/tfjs-converter --legacy-peer-deps
npm install @tensorflow/tfjs-core --legacy-peer-deps
추가적으로 필요하다고 여겨지는 @tensorflow/tfjs-backend-webgl@tensorflow/tfjs-backend-wasm@tensorflow/tfjs-backend-webgpu 은 이하 peer dependency 에 이미 포함되어 있음
특히 webgl을 tf.setBackend(’webgl’) 식으로 설정할 필요도 없음. 아래 설치하고 핵심 라이브러리를 require 하면 자동 설정됨
이하에서는 이번 프로젝트에서 구현한 hand-pose-detection, face-landmarks-detection, pose-detection 모델을 로딩하는 방법을 정리하였음.
위 모델들을 로딩한다는 것 = createDetector() 함수를 실행한다는 것
이하 방법은 model loading 시리즈 2편인 npm install 해야하는 최소한의 모듈 글을 참고해서 코드를 짜야 보다 효율적임
또한 createDetector() 함수를 오프라인으로 저장한 모델과 함께 사용하는 경우, 버전을 제대로 맞추지 않는다면 quantization 오류를 계에에에에속 맞닥뜨릴 것임. 따라서 해당 오류를 해결한 글과 함께 보길 권장함
1. CDN
CDN 이란
Contents Delivery Network : 콘텐츠 전송 네트워크
콘텐츠를 임시 저장 서버에 옮겼다가 수요가 있을 때 콘텐츠를 전달
핵심 코드 : 이하 코드는 Tensorflow-models 공식 깃헙에서 demo 코드로 명시한 방법
<!-- Require the peer dependencies of hand-pose-detection. -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter"></script>
<!-- You must explicitly require a TF.js backend if you're not using the TF.js union bundle. -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/hand-pose-detection"></script>
npm install @tensorflow/tfjsnpm install @tensorflow/tfjs-converternpm install @tensorflow/tfjs-corenpm 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! → 해결법은 맨 마지막에!
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 최신 버전 기준)
- 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점대 이후에는 포함되어있지만 그 전에는 포함되어 있지 않으므로, 보수적으로 별도 설치함)
내가 구현 시도한 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;
}
이번 프로젝트 특성 상 온라인 환경이 아니어도 (인터넷이 끊어져도) 기능이 정상적으로 작동되어야 했음.
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 사용법
위 오류 해결 방법 후보
프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI의 develop 브랜치에 npm link
프로젝트 변경될 때마다 (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 를 방지하기 위해 실행
어제 회사에서 향후 주어질 업무에 대해 차장님과 논의했다. 아마 나는 자사 제품 기능을 Node.js 로 일부 개발 + AI 개발하게 될 것 같다. 일단 너무 좋았다! 백엔드 + AI 조합 ㅎㅎ 그래서 본격적인 업무 시작 전 pc 환경설정을 하는 과정에서 다른 팀원 분들과 Node.js, npm 버전을 맞추어야 했고, 목표 버전은 Node.js는 v16.20.0, npm은 9.6.4이다. 이 때 npm은 Node Package Manager의 약자로 자바스크립트 코드 언어를 위한 노드 패키지를 관리해 주는 툴이다.
1. Node.js : cmd를 이용하여 업데이트 하는 방법
npm을 이용
n 패키지를 이용한다. 구체적인 코드는 다음과 같다.
npm install -g n //global로 설치해 주어야 Node Vesion을 root에서 관리할 수 있다.
n stable // 안정 버전 설치
n latest // 최신 버전 설치
n lts // lts 버전 설치
n x.x.x // 특정 버전 설치 ( x.x.x 버전 )
n prune // 이전 버전들 삭제해 주는 명령어
nvm( Node Vesion Manager )을 이용
nvm 자체를 이용한다. 구체적인 코드는 다음과 같다.
nvm install [ version ] // 특정 버전 설치
nvm install node // 최신 버전 설치
nvm uninstall [ version ] // 이전 버전을 삭제하는 명령어
nvm alias default [version] // 여러 버전을 설치하고 필요한 환경으로 지정해 주는 명령어
2. npm :cmd를 이용하여 업데이트 하는 방법
위에서 Node.js 버전 업데이트가 npm을 이용하는 것이 있어서 사실 나는 npm 버전부터 업데이트 하려고 했다. 구체적인 코드는 다음과 같다.
npm install -g npm@9.6.4 // 특정 버전 설치 ( x.x.x 버전 )
npm install -g npm@latest // 최신 버전 설치
꼬리 문제
npm이 정상적으로 업데이트 되지 않았다. 검색하고, 생각해봐도 합리적인 원인을 찾기 어려웠다. 그 때 차장님께서 그냥 공식홈페이지 가서 설치하는 것이 빠르다고 조언을 해주셨다...ㅋㅋㅋㅋㅋㅋ 그래서 공홈 가서 릴리즈된 버전을 살펴보니 내가 설치하려 했던 npm 버전이 현재 내 Node.js 버전과 맞지 않았고, 그래서 설치가 되지 않았던 것이었다. 따라서 Node.js는 16.20.2 로 바꿔서 , npm은 9.6.4로 그대로 설치하기로 했다.
3. 공식 홈페이지를 통한 업데이트
Node.js 공식 홈페이지로 들어가 OS와 버전을 확인하고 다운로드 받으면 된다. 다만, Node.js 를 설치하면 그에 맞는 npm이 자동 설치되므로 나중에 cmd로 npm 버전을 업데이트 해주어야 한다.