Scikit-learn: Python λ‘œκΉ…μ„ μ‚¬μš©ν•˜μ—¬ μž₯κΈ° μ‹€ν–‰ μž‘μ—…μ— λŒ€ν•œ 수렴 진행 μˆ˜μ€€ 정보 보고

에 λ§Œλ“  2011λ…„ 02μ›” 12일  Β·  31μ½”λ©˜νŠΈ  Β·  좜처: scikit-learn/scikit-learn

이것은 λͺ¨λΈ APIμ—μ„œ stdout 및 verbose ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€μ‹  python의 λ‘œκΉ… λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜λŠ” μ œμ•ˆμž…λ‹ˆλ‹€.

λ‘œκΉ… λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜λ©΄ 잘 λ¬Έμ„œν™”λœ 단일 ꡬ성 μΈν„°νŽ˜μ΄μŠ€μ™€ λ‘œκΉ… APIλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μžκ°€ scikit의 μžμ„Έν•œ 정도λ₯Ό μ œμ–΄ν•˜κΈ°κ°€ 더 μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

http://docs.python.org/library/logging.html

New Feature

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λ‹€μ„― 번째 μ˜΅μ…˜μ€ μžμ„Έν•œ ν”Œλž˜κ·Έλ₯Ό μ œκ±°ν•˜κ³  λͺ¨λ“  κ³³μ—μ„œ λ‘œκΉ…μ„ μ‚¬μš©ν•˜λ©° μ‚¬μš©μžκ°€ λ‘œκΉ… APIλ₯Ό 톡해 μžμ„Έν•œ 정도λ₯Ό μ‘°μ •ν•  수 μžˆλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이것이 λ°”λ‘œ λ‘œκΉ…μ΄ μ„€κ³„λœ λͺ©μ μž…λ‹ˆλ‹€.

μ—μŠ€ν‹°λ©”μ΄ν„°λ³„ ꡬ성을 찾으면 μžμ„Έν•œ 정보 제거λ₯Ό μ§€μ›ν•˜κ² μŠ΅λ‹ˆλ‹€.
μ‹€λ§μŠ€λŸ½κ³  μž„μ˜μ˜ μž₯ν™©ν•œ 숫자 값이 쒋지 μ•ŠμŠ΅λ‹ˆλ‹€.
λ¬Έμ„œν™”,

verbose μ—†μ• κ³  λ‘œκΉ… μˆ˜μ€€μ„ μ‚¬μš©ν•˜λŠ” 것이 맀우 쒋을 것이라고 μƒκ°ν•©λ‹ˆλ‹€. λ‚΄κ°€ λ³Ό μˆ˜μžˆλŠ” μœ μΌν•œ 단점은 λ‘œκΉ…μ„ μ•½κ°„ 덜 κ²€μƒ‰ν•˜κ²Œ λ§Œλ“ λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

λͺ¨λ“  31 λŒ“κΈ€

https://github.com/GaelVaroquaux/scikit-learn/tree/progress_logger μ—μ„œ 이에 λŒ€ν•œ μž‘μ—…μ΄ μ‹œμž‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

남은 일은 μ•„λ§ˆλ„ μƒλ‹Ήνžˆ 기계적인 μž‘μ—…μΌ κ²ƒμž…λ‹ˆλ‹€.

μƒˆλ‘œμš΄ Gradient Boosting λͺ¨λ“ˆμ—λ„ μž‘μ—…μ΄ μžˆμŠ΅λ‹ˆλ‹€.

λ‚΄ κ²½ν—˜μƒ λ‘œκΉ…μ€ μ‹€μ œλ‘œ μ‚¬μš©ν•˜κΈ°κ°€ 쉽지 μ•ŠμœΌλ―€λ‘œ -1μž…λ‹ˆλ‹€.

이 μž‘μ—…μ„ ν•˜λŠ” μ‚¬λžŒμ΄ μžˆμŠ΅λ‹ˆκΉŒ?

기본적으둜 STDOUT에 μΈμ‡„ν•˜λŠ” 둜거λ₯Ό μΆ”κ°€ν•˜λŠ” 것은 μ–΄λ–»μŠ΅λ‹ˆκΉŒ? μƒλ‹Ήνžˆ 간단해야 ν•©λ‹ˆλ‹€. 맞죠?

이 λ¬Έμ œλŠ” 2011λ…„λΆ€ν„° 곡개된 문제인데 해결될지 κΆκΈˆν•©λ‹ˆλ‹€. RFECV(https://github.com/scikit-learn/scikit-learn/blob/a24c8b464d094d2c468a16ea9f8bf8d42d949f84/sklearn/feature_selection/rfe.py#L273)μ—μ„œ 이 λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. 진행 상황을 μΈμ‡„ν•˜κ³  μ‹Άμ—ˆμ§€λ§Œ κΈ°λ³Έ 상세 μΈμ‡„λŠ” λ„ˆλ¬΄ λ§Žμ€ λ©”μ‹œμ§€λ₯Ό μΈμ‡„ν•©λ‹ˆλ‹€. 이 μž‘μ—…μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ sys.stdout λ₯Ό μ›μˆ­μ΄ νŒ¨μΉ˜ν•˜κ³  싢지 μ•Šμ•˜μœΌλ©° 둜거λ₯Ό μž¬μ •μ˜ν•˜λŠ” 것이 κ°„λ‹¨ν•˜κ³  κΉ¨λ—ν•œ μ†”λ£¨μ…˜μ΄ 될 κ²ƒμž…λ‹ˆλ‹€.

#8105 및 #10973κ³Ό 같이 sklearnμ—μ„œ μ‹€μ œ λ‘œκ·ΈμΈμ„ 톡해 ν˜œνƒμ„ λ³Ό 수 μžˆλŠ” λ‹€λ₯Έ λ°œν–‰μ΄ μžˆμŠ΅λ‹ˆλ‹€. μ „λ°˜μ μœΌλ‘œ λ‘œκΉ…μ€ sklearn에 큰 도움이 될 것이라고 μƒκ°ν•©λ‹ˆλ‹€.

당신은 그것에 λŒ€ν•΄ μž‘μ—…μ„ ν™˜μ˜ν•©λ‹ˆλ‹€. μ•„λ§ˆλ„ 콜백 μ‹œμŠ€ν…œμ΄
λ²Œμ±„ 반좜

λ‚˜λŠ” μ§€κΈˆ μ•½κ°„ λ°”μ˜μ§€λ§Œ μ–΄λ–€ ν˜•νƒœλ‘œλ“  skleanμ—μ„œ μ‚¬μš©μž μ •μ˜ κ°€λŠ₯ν•œ λ‘œκΉ…μ„ μ§€μ›ν•©λ‹ˆλ‹€(비둝 ν‘œμ€€ 파이썬 λ‘œκΉ…μ„ μ„ ν˜Έν•˜μ§€λ§Œ).

scikit-learn이 λ‘œκΉ…μ„ μ‚¬μš©ν•˜κΈ° μ‹œμž‘ν•  λ•Œ verbose=True κ°€ 무엇을 μ˜λ―Έν•˜λŠ”μ§€μ— λŒ€ν•œ λ…Όμ˜κ°€ μžˆμ—ˆμŠ΅λ‹ˆκΉŒ? μš°λ¦¬λŠ” 이것을 dask-mlμ—μ„œ μ•½κ°„ 닀루고 μžˆμŠ΅λ‹ˆλ‹€: https://github.com/dask/dask-ml/pull/528.

λΌμ΄λΈŒλŸ¬λ¦¬κ°€ λ‘œκΉ… ꡬ성을 μˆ˜ν–‰ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€λŠ” 점을 κ°μ•ˆν•  λ•Œ μ μ ˆν•˜κ²Œ λ‘œκΉ…ν•˜λ„λ‘ "μ‘μš© ν”„λ‘œκ·Έλž¨"(단지 슀크립트 λ˜λŠ” λŒ€ν™”μ‹ μ„Έμ…˜μΌ 수 있음)을 κ΅¬μ„±ν•˜λŠ” 것은 μ‚¬μš©μžμ˜ λͺ«μž…λ‹ˆλ‹€. 이것은 항상 μ˜¬λ°”λ₯΄κ²Œ μˆ˜ν–‰ν•˜λŠ” 것이 쉽지 μ•ŠμŠ΅λ‹ˆλ‹€.

https://github.com/dask/dask-ml/pull/528의 λ‚΄ μ œμ•ˆμ€ verbose=True κ°€ "λ‚˜λ₯Ό μœ„ν•΄ μΌμ‹œμ μœΌλ‘œ λ‘œκΉ… ꡬ성"을 μ˜λ―Έν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μ»¨ν…μŠ€νŠΈ κ΄€λ¦¬μžλ₯Ό μ‚¬μš©ν•˜μ—¬ λ‘œκΉ…μ„ ꡬ성 ν•  수 있으며 scikit-learn은 INFO μˆ˜μ€€ λ©”μ‹œμ§€κ°€ ν˜„μž¬ λ™μž‘κ³Ό μΌμΉ˜ν•˜λ„λ‘ stdout에 μΈμ‡„λ˜λ„λ‘ ν•©λ‹ˆλ‹€.

μΌμ‹œμ μœΌλ‘œ ν•Έλ“€λŸ¬ 섀정이 ν•΄λ‹Ή μ„€μ •κ³Ό κ΄€λ ¨λ˜μ–΄ μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.
μΆ”μ •κΈ° λ˜λŠ” μΆ”μ •κΈ° μœ ν˜•?

dask/dask-ml#528μ—μ„œ λ‚΄ μ œμ•ˆμ€ verbose=Trueκ°€ "λ‚˜λ₯Ό μœ„ν•΄ μΌμ‹œμ μœΌλ‘œ λ‘œκΉ… ꡬ성"을 μ˜λ―Έν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

이것은 쒋은 κ· ν˜•μΈ 것 κ°™μŠ΅λ‹ˆλ‹€. λ‘œκΉ… λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜λŠ” 것은 그닀지 μ‚¬μš©μž μΉœν™”μ μ΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 또 λ‹€λ₯Έ "ν•΄ν‚Ή"은 기본적으둜 info ν•˜λŠ” κ²ƒμ΄μ§€λ§Œ μ‚¬μš©μžκ°€ verbose=True ν•˜λ©΄ λ‘œκ·Έκ°€ warning 둜 올라갈 수 μžˆμŠ΅λ‹ˆλ‹€. 기본적으둜 κ²½κ³ κ°€ ν‘œμ‹œλ˜κΈ° λ•Œλ¬Έμ— μž‘λ™ν•©λ‹ˆλ‹€.

μ‚¬μš©μžκ°€ 더 λ§Žμ€ 것을 μš”μ²­ν•  λ•Œ νŠΉμ • λ©”μ‹œμ§€μ˜ μˆ˜μ€€μ„ λ³€κ²½ν•˜λŠ” 것 κ°™μ•„μš”
μžμ„Έν•œ μ •λ³΄λŠ” λ‘œκΉ… λͺ¨λ“ˆμ˜ μ˜λ―Έμ™€ μ •ν™•νžˆ λ°˜λŒ€μž…λ‹ˆλ‹€.
μΌν•˜λ‹€. κ·ΈλŸ¬λ‚˜ 둜컬 ν•Έλ“€λŸ¬λŠ” κ²½κ³ μ—μ„œ λ””λ²„κ·Έλ‘œ 변경될 수 μžˆμŠ΅λ‹ˆλ‹€.
μžμ„Έν•œ λ‚΄μš©μ΄ 증가함에 따라 슀트림의 μˆ˜μ€€

@jnothman의 μ˜κ²¬μ€ λ‚΄ 생각과 μΌμΉ˜ν•©λ‹ˆλ‹€. scikit-learn은 항상 λ©”μ‹œμ§€λ₯Ό 내보내고 verbose ν‚€μ›Œλ“œλŠ” 둜거 μˆ˜μ€€κ³Ό 처리기λ₯Ό μ œμ–΄ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ 둜컬 ν•Έλ“€λŸ¬λŠ” κ²½κ³ μ—μ„œ λ””λ²„κ·Έλ‘œ 변경될 수 μžˆμŠ΅λ‹ˆλ‹€.
μžμ„Έν•œ λ‚΄μš©μ΄ 증가함에 따라 슀트림의 μˆ˜μ€€

μ’‹μ•„, μ΄κ²ƒμœΌλ‘œ κ°€μž. ν˜„μž¬ λ‘œκΉ… μˆ˜μ€€μ€ https://docs.python.org/3/library/logging.html#logging -levelsμž…λ‹ˆλ‹€. 기본적으둜 기본적으둜 내보내지 μ•ŠλŠ” INFO μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. verbose=1 일 λ•Œ ν•Έλ“€λŸ¬ λ³€κ²½ 정보 -> κ²½κ³  및 디버그 -> 정보가 μžˆμŠ΅λ‹ˆλ‹€. verbose>=2 μ„€μ •ν•˜λ©΄ μ—¬μ „νžˆ 정보 -> κ²½κ³ κ°€ μžˆμ§€λ§Œ 디버그 -> 경고도 있으며 μΆ”μ •κΈ°λŠ” verbose>=2 λ₯Ό "μžμ„Έν•œ λ‚΄μš©μ΄ 증가함에 따라 더 λ§Žμ€ 디버그 λ©”μ‹œμ§€λ₯Ό 내보냄"을 μ˜λ―Έν•˜λ„λ‘ 해석할 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜λ―ΈλŠ” 좔정기에 따라 λ‹€λ₯Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

μ–΄λ–»κ²Œ μƒκ°ν•˜λ‚˜μš”?

μ•ˆλ…•ν•˜μ„Έμš”, μ €λŠ” 이 λ¬Έμ œμ— 관심이 λ§ŽμŠ΅λ‹ˆλ‹€. μ €λŠ” logging λŒ€ν•œ μ•½κ°„μ˜ κ²½ν—˜μ΄ 있으며 일뢀 ν•©μ˜μ™€ κ³„νšμ— λ„λ‹¬ν•˜λ©΄ μ—¬κΈ°μ—μ„œ κ°œμ„  사항을 κ΅¬ν˜„ν•˜λŠ” 데 도움을 μ£Όκ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

여기에 μ–ΈκΈ‰λœ 아이디어λ₯Ό μš”μ•½ν•˜λŠ” 데 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

  1. 콜백 νŒ¨ν„΄ μ‚¬μš©
  2. verbose 에 따라 λ©”μ‹œμ§€ μˆ˜μ€€ λ³€κ²½
    if verbose:
        logger.debug(message)
    else:
        logger.info(message)
  1. 의 μˆ˜μ€€ λ³€κ²½ logger 에 따라 verbose
    if verbose:
        logger.selLevel("DEBUG")
  1. μžμ„Έν•œ λ‚΄μš©μ— 따라 DEBUG μˆ˜μ€€μ˜ ν•Έλ“€λŸ¬ μΆ”κ°€
    if verbose:
        verbose_handler = logging.StreamHandler()
        verbose_handler.setLevel("DEBUG")
        logger.addHandler(verbose_handler)

이 μ˜΅μ…˜μ— λŒ€ν•œ λ‚˜μ˜ 견해:

μ˜΅μ…˜ 1 λ˜λŠ” μ˜΅μ…˜ 4κ°€ κ°€μž₯ μ’‹μŠ΅λ‹ˆλ‹€.

  • μ˜΅μ…˜ 1(콜백)은 κ°€μž₯ λΆˆκ°€μ§€λ‘ μ μ΄λΌλŠ” μ μ—μ„œ μ’‹μŠ΅λ‹ˆλ‹€(μ‚¬λžŒλ“€μ΄ μ›ν•˜λŠ” λŒ€λ‘œ 기둝할 수 있음). κ·ΈλŸ¬λ‚˜ λ©”μ‹œμ§•/μƒνƒœ 캑처 κ΄€μ μ—μ„œ μœ μ—°μ„±μ΄ λ–¨μ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. (μ½œλ°±μ€ λ‚΄λΆ€ 루프 λ°˜λ³΅λ‹Ή ν•œ 번 λ˜λŠ” ν•œ 번만 ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ?)
  • μ˜΅μ…˜ 2, μ—¬κΈ°μ—μ„œ λ…Όμ˜ν•œ 바와 같이 logging 라이브러리λ₯Ό μ˜€μš©ν•˜κ³  μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.
  • μ˜΅μ…˜ 3은 μž‘λ™ν•˜μ§€λ§Œ logging 라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ” λͺ©μ μ˜ 일뢀λ₯Ό λ¬΄νš¨ν™”ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. sklearn이 logging λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μ‚¬μš©μžλŠ” logging 자체λ₯Ό 톡해 μžμ„Έν•œ 정도λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€(예: import logging; logging.getLogger("sklearn").setLevel("DEBUG") .
  • μ˜΅μ…˜ 4λŠ” μ•„λ§ˆλ„ κ°€μž₯ ν‘œμ€€μ μΌ κ²ƒμž…λ‹ˆλ‹€. λ¬Έμ„œλŠ” NullHandler μ΄μ™Έμ˜ 라이브러리 μ½”λ“œμ—μ„œ ν•Έλ“€λŸ¬λ₯Ό μƒμ„±ν•˜μ§€ _not_ μ œμ•ˆν•˜μ§€λ§Œ sklearn에 verbose ν”Œλž˜κ·Έκ°€ μžˆλ‹€λŠ” 점을 κ°μ•ˆν•  λ•Œ μ—¬κΈ°μ—μ„œ μ˜λ―Έκ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 이 경우 둜그 μΈμ‡„λŠ” 라이브러리의 "κΈ°λŠ₯"μž…λ‹ˆλ‹€.

λ‹€μ„― 번째 μ˜΅μ…˜μ€ verbose ν”Œλž˜κ·Έλ₯Ό μ œκ±°ν•˜κ³  λͺ¨λ“  κ³³μ—μ„œ logging λ₯Ό μ‚¬μš©ν•˜λ©° μ‚¬μš©μžκ°€ logging APIλ₯Ό 톡해 μžμ„Έν•œ 정도λ₯Ό μ‘°μ •ν•  수 μžˆλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이것이 λ°”λ‘œ logging κ°€ μ„€κ³„λœ μ΄μœ μž…λ‹ˆλ‹€.

@grisaitis κ°μ‚¬ν•©λ‹ˆλ‹€! https://github.com/scikit-learn/scikit-learn/issues/17439 및 https://github.com/scikit-learn/scikit-learn/pull/16925#issuecomment -638956487μ—μ„œ 보닀 졜근의 κ΄€λ ¨ 토둠을 μ°Έμ‘° ν•˜μ‹­μ‹œμ˜€ . (콜백 κ΄€λ ¨). κ·€ν•˜μ˜ 도움은 λŒ€λ‹¨νžˆ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€. μ£Όμš” λ¬Έμ œλŠ” 아직 μ–΄λ–€ μ ‘κ·Ό 방식이 κ°€μž₯ 쒋을지 κ²°μ •ν•˜μ§€ λͺ»ν–ˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. :)

μ—μŠ€ν‹°λ©”μ΄ν„°λ³„ ꡬ성을 찾으면 μžμ„Έν•œ 정보 제거λ₯Ό μ§€μ›ν•˜κ² μŠ΅λ‹ˆλ‹€.
μ‹€λ§μŠ€λŸ½κ³  μž„μ˜μ˜ μž₯ν™©ν•œ 숫자 값이 쒋지 μ•ŠμŠ΅λ‹ˆλ‹€.
등을 λ¬Έμ„œν™”ν•©λ‹ˆλ‹€. ν΄λž˜μŠ€λ³„ ꡬ성은 λ‹€μŒμ„ 톡해 μ²˜λ¦¬λ©λ‹ˆλ‹€.
μ—¬λŸ¬ scikit-learn 둜거 이름.

λ‹€μ„― 번째 μ˜΅μ…˜μ€ μžμ„Έν•œ ν”Œλž˜κ·Έλ₯Ό μ œκ±°ν•˜κ³  λͺ¨λ“  κ³³μ—μ„œ λ‘œκΉ…μ„ μ‚¬μš©ν•˜λ©° μ‚¬μš©μžκ°€ λ‘œκΉ… APIλ₯Ό 톡해 μžμ„Έν•œ 정도λ₯Ό μ‘°μ •ν•  수 μžˆλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이것이 λ°”λ‘œ λ‘œκΉ…μ΄ μ„€κ³„λœ λͺ©μ μž…λ‹ˆλ‹€.

μ—μŠ€ν‹°λ©”μ΄ν„°λ³„ ꡬ성을 찾으면 μžμ„Έν•œ 정보 제거λ₯Ό μ§€μ›ν•˜κ² μŠ΅λ‹ˆλ‹€.
μ‹€λ§μŠ€λŸ½κ³  μž„μ˜μ˜ μž₯ν™©ν•œ 숫자 값이 쒋지 μ•ŠμŠ΅λ‹ˆλ‹€.
λ¬Έμ„œν™”,

verbose μ—†μ• κ³  λ‘œκΉ… μˆ˜μ€€μ„ μ‚¬μš©ν•˜λŠ” 것이 맀우 쒋을 것이라고 μƒκ°ν•©λ‹ˆλ‹€. λ‚΄κ°€ λ³Ό μˆ˜μžˆλŠ” μœ μΌν•œ 단점은 λ‘œκΉ…μ„ μ•½κ°„ 덜 κ²€μƒ‰ν•˜κ²Œ λ§Œλ“ λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ˜ν•œ λ‘œκΉ…μ΄ μ œκ³΅ν•˜λŠ” ν•œ κ°€μ§€λŠ” λ¬Έμžμ—΄λΏλ§Œ μ•„λ‹ˆλΌ 각 λ‘œκΉ… λ©”μ‹œμ§€μ— μΆ”κ°€ 정보λ₯Ό 첨뢀할 수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έλž˜μ„œ μœ μš©ν•œ κ²ƒλ“€μ˜ 전체 λ”•μ…”λ„ˆλ¦¬. λ”°λΌμ„œ ν•™μŠ΅ 쀑 손싀을 λ³΄κ³ ν•˜λ €λ©΄ κ·Έλ ‡κ²Œ ν•˜κ³  숫자 값을 μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ 숫자 값을 숫자둜 μ €μž₯ν•˜κ³  이λ₯Ό μ‚¬μš©ν•˜μ—¬ logger.debug("Current loss: %(loss)s", {'loss': loss}) 와 같은 μ‚¬μš©μž μΉœν™”μ μΈ λ¬Έμžμ—΄ ν˜•μ‹μ„ 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 그것이 일반적으둜 맀우 μœ μš©ν•˜λ‹€λŠ” 것을 μ•Œμ•˜κ³  sklearn이 그것을 κ³΅κ°œν•œλ‹€λ©΄ μ’‹μ•„ν•  κ²ƒμž…λ‹ˆλ‹€.

λͺ¨λ“ˆ λ˜λŠ” μΆ”μ •κΈ° μˆ˜μ€€ 둜거λ₯Ό κ°–λŠ” 것은 μ§€κΈˆμœΌλ‘œμ„œλŠ” μ•½κ°„ κ³Όν•˜λ‹€κ³  μƒκ°ν•˜λ©° λ‚˜μ€‘μ— ν™•μž₯ν•  수 μžˆλŠ” κ°„λ‹¨ν•œ κ²ƒμœΌλ‘œ μ‹œμž‘ν•΄μ•Ό ν•©λ‹ˆλ‹€.
λ˜ν•œ μš°λ¦¬κ°€ 무엇을 ν•˜λ“  μ‚¬μš©μžκ°€ ν˜„μž¬ λ™μž‘μ„ ν•©λ¦¬μ μœΌλ‘œ μ‰½κ²Œ μž¬ν˜„ν•  수 μžˆλ„λ‘ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‘œκΉ…κ³Ό joblibλŠ” μ–΄λ–»κ²Œ μƒν˜Έ μž‘μš©ν•©λ‹ˆκΉŒ? λ‘œκΉ… μˆ˜μ€€μ€ μœ μ§€λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€(μ˜ˆμƒλŒ€λ‘œ).

import logging
logger = logging.getLogger('sklearn')
logger.setLevel(2)

def get_level():
    another_logger = logging.getLogger('sklearn')
    return another_logger.level

results = Parallel(n_jobs=2)(
    delayed(get_level)() for _ in range(2)
)
results

```
[0, 0]

But that's probably not needed, since this works:
```python
import logging
import sys
logger = logging.getLogger('sklearn')
logger.setLevel(1)

handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)


def log_some():
    another_logger = logging.getLogger('sklearn')
    another_logger.critical("log something")

results = Parallel(n_jobs=2)(
    delayed(log_some)() for _ in range(2)
)

μ†”μ§νžˆ, λ‚˜λŠ” 이것이 μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ™„μ „νžˆ ν™•μ‹ ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€.

stdoutκ³Ό stderr은 λͺ¨λ‘ jupyter btw에 ν‘œμ‹œλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ‚΄ 꿈: ν•œ μ€„λ‘œ ν˜„μž¬ λ™μž‘μ˜ κ·Όμ‚¬μΉ˜λ₯Ό 얻을 수 μžˆμ§€λ§Œ λŒ€μ‹  진행λ₯  ν‘œμ‹œμ€„μ΄λ‚˜ ν”Œλ‘― μˆ˜λ ΄μ„ μ‰½κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

re verbose: verboseλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 더 깨끗할 수 μžˆμ§€λ§Œ verboseλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  μΆ”μ •κΈ° μˆ˜μ€€ λ‘œκΉ…μ΄ μ—†μœΌλ©΄ ν•˜λ‚˜μ˜ μΆ”μ •κΈ°λ₯Ό κΈ°λ‘ν•˜μ§€λ§Œ λ‹€λ₯Έ 것은 κΈ°λ‘ν•˜μ§€ μ•ŠλŠ” 것이 쑰금 더 κΉŒλ‹€λ‘œμ›Œμ§‘λ‹ˆλ‹€. κ·Έλž˜λ„ μ‚¬μš©μžκ°€ λ©”μ‹œμ§€λ₯Ό ν•„ν„°λ§ν•˜λ„λ‘ ν•˜λŠ” 것이 μ’‹λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš”, μΉœμ ˆν•œ λ‹΅λ³€κ³Ό 정보 κ°μ‚¬ν•©λ‹ˆλ‹€. λ‚˜λŠ” λ‹€λ₯Έ 문제λ₯Ό 읽고 λͺ‡ 가지 생각이 μžˆμŠ΅λ‹ˆλ‹€.

joblib λŠ” κΉŒλ‹€λ‘œμšΈ κ²ƒμž…λ‹ˆλ‹€. κ·Έλž˜λ„ λͺ‡ 가지 아이디어가 μžˆμŠ΅λ‹ˆλ‹€.

@amueller 맀우 μ΄μƒν•©λ‹ˆλ‹€. λ‚˜λŠ” λ‹Ήμ‹ μ˜ 예λ₯Ό μž¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. 가지와 μž‘μ—… ν•  concurrent.futures.ProcessPoolExecutor λ‚΄κ°€ μƒκ°ν•˜κΈ°μ—, joblib μš©λ„λ₯Ό ...

joblib κ°€ logging 의 μƒνƒœλ₯Ό νŒŒκ΄΄ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. μ–΄λ–€ joblib μ „λ¬Έκ°€κ°€ 무슨 일이 일어날 수 μžˆλŠ”μ§€μ— λŒ€ν•œ 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ?

import concurrent.futures
import logging
import os

logger = logging.getLogger("demoπŸ™‚")
logger.setLevel("DEBUG")

handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter("%(process)d (%(processName)s) %(levelname)s:%(name)s:%(message)s")
)
logger.addHandler(handler)

def get_logger_info(_=None):
    another_logger = logging.getLogger("demoπŸ™‚")
    print(os.getpid(), "another_logger:", another_logger, another_logger.handlers)
    another_logger.warning(f"hello from {os.getpid()}")
    return another_logger

if __name__ == "__main__":
    print(get_logger_info())

    print()
    print("concurrent.futures demo...")
    with concurrent.futures.ProcessPoolExecutor(2) as executor:
        results = executor.map(get_logger_info, range(2))
        print(list(results))

    print()
    print("joblib demo (<strong i="17">@amueller</strong>'s example #2)...")
    from joblib import Parallel, delayed
    results = Parallel(n_jobs=2)(delayed(get_logger_info)() for _ in range(2))
    print(results)

μ–΄λ–€ 좜λ ₯

19817 another_logger: <Logger demoπŸ™‚ (DEBUG)> [<StreamHandler <stderr> (NOTSET)>]
19817 (MainProcess) WARNING:demoπŸ™‚:hello from 19817
<Logger demoπŸ™‚ (DEBUG)>

concurrent.futures demo...
19819 another_logger: <Logger demoπŸ™‚ (DEBUG)> [<StreamHandler <stderr> (NOTSET)>]
19819 (SpawnProcess-1) WARNING:demoπŸ™‚:hello from 19819
19819 another_logger: <Logger demoπŸ™‚ (DEBUG)> [<StreamHandler <stderr> (NOTSET)>]
19819 (SpawnProcess-1) WARNING:demoπŸ™‚:hello from 19819
[<Logger demoπŸ™‚ (DEBUG)>, <Logger demoπŸ™‚ (DEBUG)>]

joblib demo (<strong i="21">@amueller</strong>'s example #2)...
19823 another_logger: <Logger demoπŸ™‚ (WARNING)> []
hello from 19823
19823 another_logger: <Logger demoπŸ™‚ (WARNING)> []
hello from 19823
[<Logger demoπŸ™‚ (DEBUG)>, <Logger demoπŸ™‚ (DEBUG)>]

메인 ν”„λ‘œμ„ΈμŠ€μ˜ 메인 λ‘œκ±°μ— λ‘œκΉ… λ©”μ‹œμ§€λ₯Ό 보내도둝 joblibκ°€ μƒμ„±ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€λ₯Ό ꡬ성해야 ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 그러면 메인 ν”„λ‘œμ„ΈμŠ€μ—μ„œλ§Œ λ‘œκΉ…μ„ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이것 λ˜λŠ” 이것 κ³Ό 같은 것 . λ”°λΌμ„œ λ‘œκΉ… 큐 싱크와 μ†ŒμŠ€κ°€ 있으며 ν•¨κ»˜ 묢을 수 μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” ν΄λŸ¬μŠ€ν„°μ—μ„œ 이것을 μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  μ»΄ν“¨ν„°μ˜ λͺ¨λ“  μž‘μ—…μžμ˜ λͺ¨λ“  λ‘œκΉ…μ„ 쀑앙 μœ„μΉ˜λ‘œ 보내 μ‚¬μš©μžμ˜ 컴퓨터에 ν‘œμ‹œν•©λ‹ˆλ‹€.

@mitar λ™μ˜ν•©λ‹ˆλ‹€. 그게 μ΅œμ„ μ˜ 선택일 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. (λ°˜λ“œμ‹œ λ„€νŠΈμ›Œν¬ 기반 νλŠ” μ•„λ‹ˆμ§€λ§Œ ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신 큐)

μ €λŠ” μ‹€μ œλ‘œ logging 의 QueueHandler / QueueListener λ₯Ό μ‚¬μš©ν•˜μ—¬ 예제λ₯Ό μ½”λ”©ν•˜κ³  있으며 joblib 및 concurrent.futures 둜 ν…ŒμŠ€νŠΈν•©λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ λ”°λ₯Ό κ²ƒμž…λ‹ˆλ‹€.

λ‹€λ₯Έ μ œμ•ˆλ„ μ’‹μ•„ν•©λ‹ˆλ‹€.

λ˜ν•œ λ‘œκΉ…μ΄ μ œκ³΅ν•˜λŠ” ν•œ κ°€μ§€λŠ” λ¬Έμžμ—΄λΏλ§Œ μ•„λ‹ˆλΌ 각 λ‘œκΉ… λ©”μ‹œμ§€μ— μΆ”κ°€ 정보λ₯Ό 첨뢀할 수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έλž˜μ„œ μœ μš©ν•œ κ²ƒλ“€μ˜ 전체 λ”•μ…”λ„ˆλ¦¬. λ”°λΌμ„œ ν•™μŠ΅ 쀑 손싀을 λ³΄κ³ ν•˜λ €λ©΄ κ·Έλ ‡κ²Œ ν•˜κ³  숫자 값을 μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ 숫자 값을 숫자둜 μ €μž₯ν•˜κ³  이λ₯Ό μ‚¬μš©ν•˜μ—¬ logger.debug("Current loss: %(loss)s", {'loss': loss}) 와 같은 μ‚¬μš©μž μΉœν™”μ μΈ λ¬Έμžμ—΄ ν˜•μ‹μ„ 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 그것이 일반적으둜 맀우 μœ μš©ν•˜λ‹€λŠ” 것을 μ•Œμ•˜κ³  sklearn이 그것을 κ³΅κ°œν•œλ‹€λ©΄ μ’‹μ•„ν•  κ²ƒμž…λ‹ˆλ‹€.

extra λ§€κ°œλ³€μˆ˜μ™€ μ‚¬μš©μž μ •μ˜ ν•Έλ“€λŸ¬ 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°€μš°μŠ€ ν˜Όν•© λͺ¨λΈλ§μ˜ μ‹œκ°ν™”λ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. μƒνƒœλ₯Ό μ „λ‹¬ν•˜κ³  μ‚¬μš©μžκ°€ μƒνƒœλ₯Ό μ²˜λ¦¬ν•˜λŠ” 방법을 κ²°μ •ν•˜λ„λ‘ ν•˜λŠ” 데 맀우 ν›Œλ₯­ν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€.

λ˜ν•œ λ‚΄κ°€ μœ„μ—μ„œ μ•Œμ•„μ°¨λ¦° joblib 의 νŠΉμ΄μ μ„ λ‹€μ‹œ ... λ‚˜λŠ” 그것을 λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜ μžˆλŠ” κ·ΈλŒ€λ‘œ 받아듀일 κ²ƒμž…λ‹ˆλ‹€. μ–΄μ¨Œλ“  λŒ€κΈ°μ—΄ 기반 λ””μžμΈμ΄ κ°€μž₯ μœ μ—°ν•  κ²ƒμž…λ‹ˆλ‹€.

λ‚΄κ°€ 생각할 수 μžˆλŠ” QueueHandler μ‚¬μš©μ˜ μœ μΌν•œ μ œν•œ 사항은 extra μƒνƒœ( logger.debug("message", extra={...} )κ°€ extra dictκ°€ 큐에 λŒ€ν•΄ 직렬화 κ°€λŠ₯ν•΄μ•Ό ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έλž˜μ„œ numpy 배열이 μ—†μŠ΅λ‹ˆλ‹€. :/ λ‹€λ₯Έ λ¬Έμ œλŠ” 생각할 수 μ—†μ§€λ§Œ

μ €λŠ” μ‹€μ œλ‘œ μ§€κΈˆ QueueHandler / QueueListenerλ₯Ό μ‚¬μš©ν•˜μ—¬ 예제λ₯Ό μ½”λ”©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

예, μ†ŒμΌ“μ„ ν†΅ν•œ 전솑이 μ–Έμ œ μ°¨λ‹¨λ˜λŠ”μ§€ μ•Œ 수 μ—†κ³  λ‘œκΉ… μ°¨λ‹¨μœΌλ‘œ 인해 λͺ¨λΈ 속도λ₯Ό λŠ¦μΆ”κ³  싢지 μ•ŠκΈ° λ•Œλ¬Έμ— 항상 λŒ€κΈ°μ—΄ 처리기λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ˜ν•œ extra λ₯Ό μ‚¬μš©ν•  ν•„μš”μ‘°μ°¨ μ—†μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” logger.debug("message %(foo)s", {'foo': 1, 'bar': 2}) κ°€ νš¨κ³Όκ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

예, μ†ŒμΌ“μ„ ν†΅ν•œ 전솑이 μ–Έμ œ μ°¨λ‹¨λ˜λŠ”μ§€ μ•Œ 수 μ—†κ³  λ‘œκΉ… μ°¨λ‹¨μœΌλ‘œ 인해 λͺ¨λΈ 속도λ₯Ό λŠ¦μΆ”κ³  싢지 μ•ŠκΈ° λ•Œλ¬Έμ— 항상 λŒ€κΈ°μ—΄ 처리기λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

joblib μΌ€μ΄μŠ€μ˜ 경우 QueueHandler / QueueListener λ₯Ό κ΅¬ν˜„ν–ˆλ‹€λ©΄ ν”„λ‘œμ„ΈμŠ€ 풀에 μ–΄λ–€ μƒνƒœλ₯Ό 전달해야 ν• κΉŒμš”? κ·Έλƒ₯ queue , 맞죠?

λ˜ν•œ extra λ₯Ό μ‚¬μš©ν•  ν•„μš”μ‘°μ°¨ μ—†μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” logger.debug("message %(foo)s", {'foo': 1, 'bar': 2}) κ°€ νš¨κ³Όκ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

λ„€ κ°μ‚¬ν•©λ‹ˆλ‹€. ν…μŠ€νŠΈλ‘œ λ³€ν™˜ν•˜μ§€ μ•Šκ³  μƒνƒœλ₯Ό κΈ°λ‘ν•˜λŠ” 것도 μœ μš©ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ extra 에 numpy 배열을 ν¬ν•¨ν•˜κ³  jupyter λ…ΈνŠΈλΆμ˜ μ‚¬μš©μž 지정 λ‘œκΉ… ν•Έλ“€λŸ¬λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‹€μ‹œκ°„ 데이터 μ‹œκ°ν™”(μ‹œκ°μ  λ‘œκΉ…)λ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€. 이것은 sklearnμ—μ„œ 맀우 ν›Œλ₯­ν•  것이며 @rth κ°€ 콜백으둜 μœ μ‚¬ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•œ κ²ƒμ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€.

joblib의 경우 QueueHandler / QueueListenerλ₯Ό κ΅¬ν˜„ν–ˆλ‹€λ©΄ ν”„λ‘œμ„ΈμŠ€ 풀에 μ–΄λ–€ μƒνƒœλ₯Ό 전달해야 ν• κΉŒμš”? κ·Έλƒ₯ λŒ€κΈ°μ—΄, 그렇지?

λ‚˜λ„ κ·Έλ ‡κ²Œ 생각해. ν”„λ‘œμ„ΈμŠ€ 경계λ₯Ό β€‹β€‹λ„˜μ–΄ 이것을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ 닀쀑 μ²˜λ¦¬μ— λŒ€ν•œ λ¬Έμ„œν™”λœ 지원이 μžˆλŠ” 것 κ°™μœΌλ―€λ‘œ joblibμ—μ„œλ„ μž‘λ™ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ™μΌν•œ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ QueueHandler/QueueListenerλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ‘œκΉ… μ „μ†‘μ—μ„œ λ‘œκΉ… μ“°κΈ°λ₯Ό λΆ„λ¦¬ν•©λ‹ˆλ‹€. QueueHandler -> QueueListener -> 쀑앙 λ‘œκΉ… μ„œλΉ„μŠ€λ‘œ 보내기도 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ¬Έμ„œμ—μ„œ 닀쀑 처리 λŒ€κΈ°μ—΄μ„ 톡해 μž‘λ™ν•  수 μžˆλŠ” κ²ƒμ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€.

λ‚˜λŠ” 그것을 ν…μŠ€νŠΈλ‘œ λ³€ν™˜ν•˜μ§€ μ•Šκ³  μƒνƒœλ₯Ό κΈ°λ‘ν•˜λŠ” 것도 μœ μš©ν•˜λ‹€λŠ” 것을 μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

예. λ‚΄κ°€ λ§ν•˜λ €λŠ” 것은 extra λ₯Ό μ‚¬μš©ν•  ν•„μš”κ°€ μ—†μ§€λ§Œ dictλ₯Ό 직접 μ „λ‹¬ν•œ λ‹€μŒ λ©”μ‹œμ§€ ν˜•μ‹ν™”λ₯Ό μœ„ν•΄ ν•΄λ‹Ή dict의 λͺ‡ 가지 ν•­λͺ©λ§Œ μ‚¬μš©ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€(ν˜•μ‹ λ¬Έμžμ—΄μ— μ‚¬μš©λ˜λŠ” ν•­λͺ©μ΄ κ²°μ •λœλ‹€λŠ” 점에 μœ μ˜ν•˜μ‹­μ‹œμ˜€. sklearn λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ•„λ‹Œ sklearn 라이브러리 μ‚¬μš©μžμ— μ˜ν•΄ μ˜ˆμƒν•˜μ§€ λͺ»ν•œ μ„œμ‹μ„ μ§€μ •ν•˜λ„λ‘ 항상 ꡬ성할 수 μžˆμœΌλ―€λ‘œ μ •ν™•νžˆ ν…μŠ€νŠΈλ‘œ λ³€ν™˜λ˜λŠ” λ‚΄μš©μ€ μ‹€μ œλ‘œ sklearn μ œμ–΄ ν•˜μ— μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. extra λͺ¨λ“  값은 λ©”μ‹œμ§€ ν˜•μ‹μ—λ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ extra κ°€ μ–Όλ§ˆλ‚˜ μœ μš©ν•œμ§€ 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ‚˜λŠ” λ˜ν•œ μš°λ¦¬κ°€ 그것을 μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλœλ‹€κ³  λ§ν•˜λŠ” 것이 μ•„λ‹™λ‹ˆλ‹€. μ™Όμͺ½μ— μžˆλŠ” λ¬Έμžμ—΄μ˜ νŽ˜μ΄λ‘œλ“œμ™€ μΆ”κ°€ 사항이 훨씬 더 λͺ…ν™•ν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ μš°λ¦¬λŠ” λ‘˜ λ‹€ μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 단지 이 λŒ€μ•ˆμ΄ μ•Œλ €μ Έ μžˆλŠ”μ§€ ν™•μΈν•˜κ³  μ‹Άμ—ˆμŠ΅λ‹ˆλ‹€.

@grisaitis 참고둜 μ»€λ°‹μ—μ„œ 이름을 μ–ΈκΈ‰ν•˜λ©΄ β€‹β€‹μ»€λ°‹μœΌλ‘œ 무엇이든 ν•  λ•Œλ§ˆλ‹€(예: 리베이슀 λ˜λŠ” 병합 λ˜λŠ” ν‘Έμ‹œ) κ·Έ μ‚¬λžŒμ€ 이메일을 λ°›κΈ° λ•Œλ¬Έμ— 일반적으둜 ꢌμž₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ ;)

μ£„μ†‘ν•©λ‹ˆλ‹€ μ•ˆλ“œλ ˆμ•„μŠ€! 😬 μ°½ν”Όν•˜λ„€μš”... κ·Έλƒ₯ λ¬Έμ„œν™” 잘 된 컀밋을 ν•˜λ €κ³  ν–ˆλ˜ 것 λΏμ΄μ—μš” γ…‹γ…‹γ…‹γ…‹ μ•žμœΌλ‘œλŠ” ν”Όν•  κ²ƒμž…λ‹ˆλ‹€.

κ·Έ λ¦¬ν¬μ§€ν† λ¦¬μ—μ„œ QueueHandler / QueueListener 콀보λ₯Ό μ‚¬μš©ν•˜μ—¬ joblib μ—μ„œ λ‘œκΉ…μ΄ μž‘λ™ν•˜λŠ” 방법을 μ•Œμ•„λƒˆμŠ΅λ‹ˆλ‹€. 잘 μž‘λ™ν•˜λŠ” κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

첫 번째 λ‹¨κ³„λ‘œ joblib κ°€ μ‚¬μš©λ˜λŠ” sklearn의 μΌλΆ€μ—μ„œ ν•΄λ‹Ή μ ‘κ·Ό λ°©μ‹μœΌλ‘œ λ‘œκΉ…μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. μ•„λ§ˆλ„ 앙상블 λͺ¨λΈ 쀑 ν•˜λ‚˜μΌ κ²ƒμž…λ‹ˆλ‹€. μƒˆλ‘œμš΄ PR을 μ—½λ‹ˆλ‹€.

joblib의 경우 QueueHandler / QueueListenerλ₯Ό κ΅¬ν˜„ν•˜λ©΄

예, 닀쀑 처리의 경우 λ‘œκΉ… λͺ¨λ“ˆκ³Ό μ½œλ°±μ„ μ‚¬μš©ν•˜λŠ” 경우 λͺ¨λ‹ˆν„°λ§ μŠ€λ ˆλ“œ(μ—¬κΈ°μ„œλŠ” QueueListener )λ₯Ό μ‹œμž‘/쀑지해야 ν•  것 κ°™μŠ΅λ‹ˆλ‹€(https://μ—μ„œ 닀쀑 μ²˜λ¦¬κ°€ μžˆλŠ” 콜백의 λŒ€λž΅μ μΈ 예). github.com/scikit-learn/scikit-learn/pull/16925#issuecomment-656184396)

κ·Έλž˜μ„œ μœ„μ—μ„œ λ‚΄κ°€ "μž‘λ™"ν•œ μœ μΌν•œ μ΄μœ λŠ” 곡유 λ¦¬μ†ŒμŠ€ 인 stdout에 μΈμ‡„λ˜μ—ˆκ³  print λŠ” python3 λ˜λŠ” 이와 μœ μ‚¬ν•œ κ²ƒμ—μ„œ μŠ€λ ˆλ“œλ‘œλΆ€ν„° μ•ˆμ „ν•˜λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

κ·Έλž˜μ„œ μœ„μ—μ„œ λ‚΄κ°€ "μž‘λ™"ν•œ μœ μΌν•œ μ΄μœ λŠ” 곡유 λ¦¬μ†ŒμŠ€ 인 stdout에 μΈμ‡„λ˜μ—ˆκ³  μΈμ‡„λŠ” python3 λ˜λŠ” 이와 μœ μ‚¬ν•œ κ²ƒμ—μ„œ μŠ€λ ˆλ“œλ‘œλΆ€ν„° μ•ˆμ „ν•˜λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

μΈμ‡„λŠ” μŠ€λ ˆλ“œλ‘œλΆ€ν„° μ•ˆμ „ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 그듀은 단지 λ™μΌν•œ 파일 μ„€λͺ…μžλ‘œ μΈμ‡„ν•©λ‹ˆλ‹€. μ•„λ§ˆλ„ 더 였랜 μ‹œκ°„ λ™μ•ˆ μ‹€ν–‰ν•˜λ©΄ λ©”μ‹œμ§€κ°€ λ•Œλ•Œλ‘œ μΈν„°λ¦¬λΈŒλ˜κ³  행이 ν˜Όλ™λ˜λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰