첫째날
올해 서울에서 열리기로 했었던 ICSE(International Conference of Software Engineering) 2020이 결국 화상으로 개최되었다. 비록 학회장의 열띤 공기를(?) 느낄 수는 없지만 요즘의 연구 동향을 최대한 따라잡자는 마음으로 열심히 듣기로 했다.
Technical Track의 첫 날은 MIT에서 Software Safety 연구를 하고 계신 Nancy Leveson 교수님의 키노트로 시작했고, 나는 Software Security, Clones and Changes, Testing and Debugging, Deep Learning + SE, Code Summarization 세션의 페이퍼 발표를 주로 들었다.
인상깊었던 페이퍼와 세션들의 주제들을 중심으로 학회 첫째 날 배운 것 + 느낀 점을 기록해 보려고 한다.
Testing & Debugging for Deep Learning System
Deep Learning System을 테스팅/디버깅의 타겟으로 삼는 것은 최근의 SE 학계에서 꽤나 뜨거운 감자다. 모델의 Robustness나 정확도를 향상시키려는 노력은 딥러닝 학계의 주된 관심사이기도 하지만, 소프트웨어 엔지니어링의 측면에서, 기존 Traditional System을 테스트하거나 디버깅하기 위해 사용하던 기술을 어떻게 ‘딥러닝에 맞게’ 적용시킬 수 있을지에 대한 다양한 아이디어들이 존재한다.
첫째날의 Testing & Debugging for Deep Learning System 세션에서는 크게 DNN model의 오동작(misbehavior)을 탐지하는 adversarial input generation[2], Deep Learning System(Model이 아니라 System 전체를 대상으로 함)에서 주로 발생하는 Fault/Failure의 분류 체계와 그 빈도에 대한 empirical study[3, 4]가 소개되었다. DISSECTOR의 경우에는 조금 특이한데, 모델이 confidence를 가지고 있는 input과 그렇지 않은 input을 구분하는 input validation technique을 제시한다. 즉 모델 자체를 개선하거나 retraining하는 것이 아닌, 이미 deploy된 모델이 잘못된 prediction을 생성할 가능성을 최대한 줄이는 것이다. (모델의 prediction capability를 넘어서는 input(beyond-input)은 매뉴얼하게 판단하거나 다른 모델로 넘기게 된다)
[1] DISSECTOR: Input Validation for Deep Learning Applications by Crossing-layer Dissection
DISSECTOR는 현재 상황에서 조금 더 실용적인 아이디어를 제시한다. Model의 accuracy를 높이기 위해 retrain하고, 전체 시스템을 rebuild, redeploy하는 대신 모델의 handling capability를 넘어서는 input을 먼저 걸러내고 그 input에 대해서는 다른 prediction 전략을 취하자는 것이다.
하지만 어떤 input에 대해서 model의 confidence score를 online으로 수행하기 위해서는, 적은 overhead로 validation을 수행해야 하고, 그러면서도 정확하게 confident/inconfident한 input을 구분해야 한다.
DISSECTOR는 이를 위해서 기존의 trained model으로부터 sub-model들을 생성하고, 각각에 대한 target input의 snapshot들로부터 confidence score를 뽑아낸다. 이 과정이 크게 3개의 component들로 구성되어 있다.
(1) Sub-model generation: confidence를 구하기 위한 sub-model을 어떻게 뽑아내는지가 가장 궁금한 과정이었는데, 간단히 살펴보자면 주어진 DL 모델의 특정 중간 레이어에 대해서 앞부분은 그대로 사용하고, 뒷부분은 fully-connected 레이어 하나로 단순화시켜서 (with cross-entropy loss) 좀더 작은 sub-model을 얻어낸다. (그러면 weight는 어떻게 되는 걸까?) budget에 따라 여러 개의 sub-model들을 생성할 수 있다. 이 과정은 offline으로 deploy 과정에서 한 번만 수행된다. 그러면 이렇게 만들어진 sub-model들이 confidence를 결정하는 데에 어떤 역할을 할까?
(2) Prediction Snapshot Profiler

input을 실제 DL model에 제공하는 과정에서, 각 layer별로 생성된 sub-model들에 동일한 input을 제공해서 생성된 결과들은 각 레이어가 하나씩 추가되면서 partial knowledge가 얼마나 추가되는지를 어느 정도 설명할 수 있다. 각 submodel들에서 생성된 probability vector를 prediction snapshot으로 명명하고, 각 input 하나에 대응되는, snapshot들의 리스트로 이루어진 prediction profile을 만든다. 이 profile이 다음 단계의 재료로 사용된다. 이 input을 통해 모델이 얼마나 valid한 output을 생성할 수 있을지에 대한 score를 구하기 위해서다.
(3) Validity Analyzer
validity degree (=confidence score)를 구하는 과정을 살펴보기 앞서, 이 논문의 base assumption (혹은 intuition)은 앞에서 뒤로 더 많은 layer를 거쳐갈수록 모델이 prediction vector에서 점점 더 높은 confidence를 가지게 될수록, 최종적으로 만들어낸 prediction이 valid할 것이라는 생각이다.
어떤 model이 predict한 결과에 대해서 얼마나 confident한지를 판단하는 것은 explainability의 관점에서도 중요하다.
먼저 input을 전체 DL model에 통과시켜서 얻은 label이 snapshot에서도 어느 정도의 confidence로 예측되는지를 표현한 score가 논문에서 소개하는 SVscore이다. 그리고 각 스냅샷에 대한 score을 모아서, 뒤에 있는 layer로 갈수록 더 높은 confidence score를 가지는지 확인할 수 있는 최종 PVscore를 계산하게 된다.
MNIST, CIFAR-10, 100, ImageNet의 네 가지 데이터셋에 대해서 실제로 incorrectly-predicted samples에 대해서는 correctly-predicted samples보다 확연히 낮은 PVscore의 분포를 보여주었다.
기존의 state-of-the-art input validation technique인 mMutant(based on model mutation analysis), Mahalanobis(based on data-distance measurement)과의 비교는, PVscore의 threshold에 따라 valid/invalid input의 classification에 대한 AUC value로 이루어졌다. (mMutation과 Mahalanobis도 threshold에 따라서 FP/TP rate가 달라지나?)
weight parameter의 선택에 따라 best가 달라지기는 했지만, 모든 데이터셋에 대해서 DISSECTOR가 가장 정확하게 within-input과 beyond-input을 구분할 수 있는 것으로 확인되었고, 추가적으로 오버헤드 비교와 모델의 종류, weight growth type에 대해서 sensitivity analysis도 수행했다. 마지막 RQ에서는 Adversarial Input에 대해서도 성공적으로 classification을 수행하는지 확인했다.
[2] White-box Fairness Testing through Adversarial Sampling
Fairness 측면에 집중해서 individual discriminatory instance를 효과적으로 샘플링하는 방법에 대한 연구다. 현재의 state-of-the-art로는 random search나 기본적인 local search로 input space를 탐색하거나, model을 근사하는 decision tree를 만들어서 symbolic execution을 수행하는 방법 등이 제시되었다. 하지만 이들은 logistic regression이나 SVM과 같은 전통적인 ML technique을 주로 염두에 두었기 때문에, DNN에서의 성능은 그리 좋지 않았다고 한다.
Individual discriminatory instance는 정확히 어떤 형태일까? 예를 들어, Census Income dataset에서 protected attribute가 gender라고 했을 때, gender의 변경이 predict된 income에 변화를 주어서는 안 된다. 그럼에도 모델(regression model)이 어떤 input(bold로 강조한 것이 gender feature)이 [4,0,6,…, 1, .. ] => [4,0,6,…,0, .. ]로 바뀌었을 때 결과로 출력된 income 값이 바뀌는 경우, 이 input (pair)이 individual discriminatory instance가 된다.
이 연구에서 제시한 Adversarial Discrimination Finder(ADF)는 search를 guide하기 위해서 gradient를 사용하고, clustering을 사용해서 좀더 효율적인 탐색을 수행한다.
- Evaluation: fairness에 대한 평가에서 주로 쓰이는 census와 bank, credit 데이터셋에서 각각 age, race, gender를 ‘protected attribute’로 두고 얼마나 많은 individual discriminatory instance을 제한된 budget 안에 얼마나 많이 찾아내는지에 대해서 평가했다.
[3] Taxonomy of Real Faults in Deep Learning Systems
TensorFlow, Keras, PyTorch를 사용한 GitHub 프로젝트의 커밋과 이슈 1059개를 모아서 연구자들과 현업 개발자들이 직접 fault의 분류 체계를 정립한 연구다.
모델 자체의 inaccuracy도 문제가 되지만, 개발자들이 input dimension과 잘못된 hyperparameter, 메모리와 GPU 관리에서의 실수, API version 문제 등 굉장히 다양한 문제 발생의 원인이 얽혀 있었다.
- 모델을 실제로 train하고 inference하는 과정을 mocking할 수 있다면 모델 외부의 bug에 대해서는 훨씬 더 쉽게 validation할 수 있을 것 같다. 이 부분에 대해서 좀더 생각을 발전시켜 보고 싶다.
[4] An Empirical Study on Program Failrues of Deep Learning Jobs
앞의 논문과 비슷한 계열의 empirical study인데, Microsoft의 Deep learning platform(Philly)에서 발생한 4960개의 failure를 수집해서 root cause와 fix pattern까지 함께 분석한 연구다. 주요한 finding들을 옮겨 보자면,
(1) 48%의 failure이 code logic보다는 platform과의 interaction에서 발생했고, 결국 execution environment에 잘못이 있는 경우가 대다수였다. (2) 모델 러닝과 직접적으로 연관된 문제들은 모델 파라미터와 구조(아마도 dimension), API misunderstanding으로부터 비롯되었다. (3) 현재 딥러닝 시스템의 디버깅 practice는 (maybe due to the stochastic nature) 효과적으로 fault localization이 되지 않고, intermediate result를 캐시하는 등의 specific한 tool이 필요하다.
이러한 finding들을 바탕으로 platform improvement / tool support / framework improvement 등의 방향을 제시하는데, 너무 tool과 프레임워크 구현 자체에 포커스를 둔 점은 아쉽지만 좀더 현실적인 관점에서 현재의 testing/debugging practice를 어떻게 개선시킬 수 있을지 많은 정보를 주는 논문인 것 같다.
[Review] Traditional System and Deep Learning System
[Idea] Repair of Deep Neural Network rather than Retraining
Identified buggy input들을 바탕으로 모델을 retrain한다고 해도 바로 bug가 fix된다는 보장은 없을 것이다. 좀더 systematic한 방식으로 retraining을 하는 방법에 대한 approach가 있다고 deeptest keynote에서 들은 것 같은데, 그런 방식들에서 더 나아가 모델 자체의 weight나 부분적인 구조를 tuning해서 버그를 고칠 수도 있지 않을까.
[Idea] Explainable DNN Behavior
Not treat DNN model as a blackbox (industry-aspect)
Code Summarization
저번 학기에 들은 수업 프로젝트에서 code2seq를 replication 하면서 조금 더 관심을 갖게 된 분야가 code summarization이다. 코드의 한 단위를 vector embedding으로 만들어서 컨텍스트를 함축할 수 있다면, patch generation이나 method name, comment generation 등의 다양한 태스크에 사용할 수 있을 것이다.
한 세션이 통째로 code summarization에 대해서 할당된 것이 꽤나 신기했는데 (code summarization이 명확하게 태스크로 연결되지는 않기 때문에) 독창적인 태스크/목표(Goal)를 제시하면서 NLP technique을 Code에 적용하려는 시도들이 흥미로웠다.
기본적으로 Method Prediction Task가 code summarization의 evaluation 대상이 되는데, method 이름을 단순히 예측한다는 것이 practice에서 얼마나 도움이 될지에 대해서는 이견이 있을 수도 있겠다. 그래서 좀더 복잡하고 실용적인 use case, documentation을 자동으로 해 주는 것에 대한 benchmark도 결과에 함께 덧붙이게 되는데, 문제는 그런 데이터셋 자체를 construct하는 것이 꽤나 어렵다는 사실이다. 단순히 크롤링한 코드의 코멘트에는 코드의 behavior와 상관없는 많은 noise들이 존재한다. 그래서인지 이번 세션에서는 자연어와 코드가 섞여 있는 텍스트를 정확하게 태깅하고[1], 코멘트의 타입을 명확하게 분류하는[2] 데이터셋의 정제에 관한 논문들도 함께 자리하고 있었다.
[1] Posit: Simultaneously Tagging Natural and Programming Languages
Posit은 StackOverFlow나 버그 리포트, 이슈 등에서 쉽게 찾아볼 수 있는 코드와 일반적인 텍스트가 섞여 있는 상황을 대상으로 한다. 나는 이 논문이 Code Summarization으로 구분되는 이유가 아마 code summarization work의 dataset construction과 연관이 있어서가 아닐까 생각했는데, 실제로 코드를 마이닝할 때 코드를 명확하게 구분하고, 이 코드가 실제로 AST tree의 어떤 노드로 표현되는지, 이 텍스트의 품사는 무엇인지를 태깅할 수 있게 되면 코드를 Natural Language로 매핑하는 태스크에 대해서 훨씬 정확하고 품질 높은 데이터셋을 얻을 수 있을 것이다. (지금은.. code2seq 데이터셋 보면서 느꼈지만 심각한 것 같다..)
-
Target Task: language identification / PoS/AST tagging
-
Model: biLSTM network with a Conditional Random Field output layer
-
tags: AST tags from CLANG compiler, part-of-speech tags from the Stanford part-of-speech tagger
[2] CPC: Automatically Classifying and Propagating Natural Language Comments via Program analysis
[3] Suggesting Natural Method Names to Check Name Consistencies
이 연구는 기존의 method name prediction에 관한 태스크를 consistency의 관점에서 좀더 명확하게 재정의했다는 점에서 꽤 의미가 있다고 생각했다. 단순히 method 하나의 scope에서 name을 prediction하는 것이 아닌, 프로젝트 전체, 또는 클래스의 context에서 inconsistent한 method name을 탐지한다는 것이 좀더 현실적이라는 생각이 들었다.
모델 자체는 단순한 seq2seq model, 즉 RNN Encoder-Decoder로 이루어져 있는데, Implementation/Interface/Enclosing (class) 세 가지의 컨텍스트로 토큰들을 분류하고 이를 concat하여 함께 input으로 사용함으로써 성능을 높였다.
code2vec과 결과를 비교하기도 했는데, 오히려 훨씬 더 단순한 모델을 사용하면서도 token을 적절한 컨텍스트로 분류하기만 했는데도 precision에 대해서는 더 좋은 성능을 보였다.
- context를 본 것은 좋은 시도이지만, 한 컨택스트 안에 (예를 들면 같은 클래스 안에) 함께 존재하는 method들을 함께 고려하면 consistency의 측면에서 더 정확한 결과를 얻을 수 있지 않을까?
[4] Retrieval-based Neural Source Code Summarization
Testing & Debugging
Causal Testing: Understanding Defects’ Root Causes
-
Root Cause: Debugging의 과정 (fault localization, identifying patch) 자체의 의도를 생각해보면 defect의 root cause를 찾는 것이라고도 설명할 수 있겠다. 우리가 관찰할 수 있는 것은 결과로 나타난 ‘buggy behavior’이다. (test failure, crash의 형태 - 또 뭐가 있을까?) 이 논문에서는 buggy behavior을 설명할 수 있는 execution을 찾아내고 효과적으로 buggy behavior과 관련된 test를 generation하는 테크닉을 소개한다. (what is the theory of counterfactual causality?)
-
기존 debugging tool의 문제점: “디버깅을 어떻게 하면 좀더 쉽게 할 수 있을까?” 라는 SE 연구의 가장 주요한 질문으로부터 파생된 기존의 접근들은 test case들의 pass/fail 결과들을 바탕으로 코드 라인의 버그를 localize하는 SBFL, 버그 리포트나 stack trace들의 정보를 활용하는 IR-based FL, 그리고 fail을 발생시키는 input의 요소를 찾는 delta debugging 등이 있다. 이러한 테크닉들을 developer들에게 전달되는 bug-related information의 양을 줄이고 최대한 유용한 정보들만을 참조할 수 있도록 하는 접근 방법으로 통틀어 설명할 수도 있을 것 같다. 하지만, 기존에 관찰된 behavior만을 이용해서 정보의 양을 ‘충분히’ 줄이기는 쉽지 않고, 코드의 어느 부분이 failure에 기여하는지는 알 수 있지만 ‘왜’ 이런 behavior가 발생했는지에 대한 설명은 누락될 수밖에 없다. 실제로 개발자의 manual한 debugging 과정을 생각해 보면, failing 하는 케이스에 대해서 좀더 세세하게 테스트를 만들어 나가거나 관련된 코드의 stopping point를 찍어서 각 변수들의 값들을 확인하는 식으로 진행될 것이다. Causal Testing의 기본적인 아이디어는 fail하는 테스트의 execution, 또는 input을 “아주 작은 정도”로 mutate하면서 이 (input의, 또는 execution의) 변경과 behavior 사이의 causal relationship을 도출해내는 것이다.
-
Novelty: 지금껏 statistical causal inference를 root cause analysis에 도입하고자 하는 시도는 존재했지만 [Causal inference for statistical fault localization: ISSTA ‘10, Mitigating the confounding effects of program dependences for effective fault localization, FSE ‘11, Debugging with Intelligence via Probabilistic Inference] 프로그램 내의 element들에 대한 modeling에 초점을 맞춤으로써 faulty statement를 포함한 위치를 좁히는 데에 집중했다면, 이 연구에서의 접근은 fail을 일으키는 가장 작은 단위(text의 similarity 뿐만 아니라 execution trace의 similarity도 고려한다) 의 input purturbation을 수행하고, 이때 execution trace의 difference를 캡쳐함으로써 ‘cause’에 대한 결과물로 ‘location’이 자연스럽게 도출되도록 만들었다는 점에서 다른 접근을 취한 것 같다. (비슷한 work이 있었는데 내가 모르는 걸수도 있다)
-
HOLMES: A causal testing prototype 프로토타입은 Eclipse plugin 형태로 구현하였는데, 셜록 홈즈의 이름을 따서 툴 이름을 HOLMES로 지은 점이 재미있었다.
-
Comment: Debugging 과정을 자동화하는 과정에 대해 생각할 때, 지금껏 꽤 다양한 기술들이 제시되었기 때문에 존재하는 연구의 정확도를 어떻게 더 올릴 수 있을까에 대한 생각에 매몰되기가 쉬운 것 같다. 하지만 실제로 개발자들이 실제로 디버깅을 하는 과정에서, “where”이 아닌 “why”에 대한 질문에서부터 시작한다는 사실을 포착함으로써 새로운 방향을 제시한 연구라고 생각한다. 다만 테스트의 input을 modify하는 경우는 string 타입으로만 한정되어 있는데, 다양한 input에 대해서도 flexible하게 활용할 수 있을지 좀더 탐구해 보고 싶다.
A Study on the Lifecycle of Flaky Tests
Program Analysis
HyDiff: Hybrid Differential Software Analysis
HARP: Holistic Analysis for Refactoring Python-Based Analytics Programs
둘째날
아홉시부터 오전 동안 쉴새없이 이어진 Paper Presentation이었지만 재미있는 주제들이 많아서 다행히 깨어 있을 수 있었다.
Bugs and Repair라는 이름으로, Automated Program Repair(APR)에 대한 세션으로 시작했고, 오늘 아침에 이어진 Testing and Debugging 세션에서는 Information Retrieval에 집중하여 Fault Localization, Failure Root Cause Identification의 성능을 향상시킨 논문들이 주로 소개되었다.
Bugs and Repair
[1] PRECFIX: Large-Scale Patch Recommendation by Mining Defect-Patch Pairs
(SEIP: Software Engineering in Practice) Alibaba와 난양공대가 함께 진행한 만큼 industrial codebase를 활용하여 practical한 관점에서 patch recommendation을 접근했다.
-
Impractical Literature: 기존에 mining 기반 patch recommendation이 test suite나 debugging report를 요구하는데, 실제 industrial setting에서는 이런 것들이 존재하지 않는 경우가 많다. (insufficient test cases, lack of patch labels, practical requirements on diverse applications) PRECFIX에서는 개발 히스토리 상에서 확인되는 defecct-patch pair들만을 이용해 clustering을 수행함으로써 reusable patching pattern들을 추출한다.
-
Unsupervised approach로 비슷한 패턴의 defect-patch 클러스터들을 추출하고, feedback-based로 추천을 수행한다. false positive rate 22% 정도가 나왔다고 하고, 실제 Alibaba 개발자들에게 디버깅 과정에서 도움이 된다는 코멘트를 받았다고 하는데, 자세한 technical detail들을 아직 살펴보지는 않았지만 피드백을 수행한다면 몇 번 개발자들에게 recommendation이 제공되는지와, 생성된 클러스터의 크기는 어느 정도일지 궁금하다.
[2] A Systemetic Assessment of 16 Automated Repair Systems (Test Suite based) for Java Programs
(technical paper) 여기서는 Generate & Validate APR approach들을 efficiency 측면에서 평가했다. 현재까지는 patch generation의 efficiency를 고려할 때 단순히 시간을 측정했는데 (확인 필요) 당연히 이는 절대적인 기준이 될 수 없으므로 NPC(Number of patch candidates before plausible patch generated) 라는 새로운 metric을 제안하여 16개의 repair tool에 대한 benchmark를 수행한다. 정확히 같은 fault localization configuration을 사용해서 noise의 영향을 최소화했다. 논문의 finding 중에서 template-based repair이 기존에 알려진 것보다 성능이 좋지 못했다는 것이 있는데, 이 결과가 learning-based repair의 효율성을 내포하는 것인지는 모르겠다. (아직 fix 가능한 버그의 절대적인 갯수는 template-based가 가장 잘 하기 때문에..)
사실 기대하면서 들은 논문이었는데 NPC라는 metric에 대한 아이디어가 그렇게 새롭게 느껴지지는 않았고, 현재의 APR literature에서 (애초에 고칠 수 있는 버그가 굉장히 한정되어 있는 상황), 더 빨리 패치를 찾았다는 사실만으로 efficiency가 더 높다, 라고 바로 단정짓기에는 무리가 있다는 생각이 들었다. 그래도 FL의 성능과 APR tool 자체의 성능에 대한 연관성을 찾는 finding은 가치있는 것 같다.
[3] SEQUENCER: Sequence-to-Sequence Learning for End-to-End Program Repair
- Paper link: https://ieeexplore.ieee.org/document/8827954
-
SEQUENCER은 Journal-first 트랙으로 이전에 잠깐 확인했던 적 있었던 Repair 테크닉이었다. end-to-end learning을 통해 learning-based patch generation의 성능을 높였는데, 핵심이 되는 것은 copy mechanism(OOV가 발생한 word에 대해 source sequence에 있는 word를 그대로 복사해 오는 것 - 보통 NLP에서 고유명사의 경우)이다. 어떻게 보면 굉장히 간단한 해결책인데, language compression (complex preprocessing step required) 이나 variable name normalizing 등의 방법보다도 copy mechanism이 더 좋은 성능을 낸다는 author들의 설명이 있었다.
- GitHub에서 one-line modification을 수행하는 커밋들을 마이닝(cross-project)해서 seq2seq model을 훈련시켰다. 처음 듣기에는 단순히 one-line commit들을 모아서 사용하면 bug fix가 아닌 modification들도 섞여서 트레이닝이 잘 되지 않을 것 같았는데, author들에게 물어봤을 때에는 refactoring change들이 섞여 있다고만 하고 이들이 얼마만큼 존재하는지에 대해서는 답을 들을 수 없었다. 논문에 소개된 patch example들을 보니 one-line change는 보통 bugfix가 대부분이겠다는 생각은 들었다.
[4] A Study of Bug Resolution Characteristics in Popular Programming Languages
(Journal First)
- Programming Language의 특성은 debugging style에 어떤 영향을 미칠까? 명확한 인과관계는 알 수 없더라도, 어떤 상관관계가 있는지 탐구한 결과가 이 논문이다. 600개의 GitHub 프로젝트에서 30만여 개의 커밋을 모아, 10개의 programming language에 대해서 abstract한 bug resolution pattern을 추출해내고자 했다. bug reesolution time, patch size 등의 요소들을 비교했는데, 사실 결과로 주어진 finding들이 당장 repair strategy를 발전시키는 데에 어떤 도움이 되는지는 모르겠다. (ex. Ruby의 버그 resolution time은 Go의 4배이고 Java의 2.5배) 결국 약간 용두사미(?)로 static typing이 bug resolution에 중요하다는 결론을 맺고 끝나는데 (dynamic type language의 type inference system을 더 강화시켜야 하는 걸까?) 어쨌든 language별로 특성을 보는 것은 꽤 재미있는 시도였던 것 같다.
[5] Automated Bug Reproduction from User Reviews for Android Applications
- Ranking GUI components in user review: share many same words
Testing and Debugging
둘째날의 testing and debugging 세션에서는 debugging 과정 전체를 automation하려는 큰 주제보다는 특정한 시나리오 (ex. crash[1]), 또는 FL이나 디버깅 과정에서 필요한 정보의 정제[2]에 집중한 논문들이 소개되었다. 물론 이전에 journal에도 발표된, Defect Prediction에 사용되던 Version History를 SBFL과 결합한 HSFL 논문[4]에 대한 발표도 있었다. Testing에 대해서는 Regression testing과 Multimorphic testing에 대한 연구가 있었다.
[1] Debugging Crashes using Continuous Contrast Set Mining
(Industrial Track) Facebook에서 진행한 연구로써, app crash report에서 discriminative pattern을 마이닝해서 crash를 ‘분류’하려는 시도를 한다. 하지만 crash의 패턴 변화가 ‘연속적’으로 나타나기 때문에, 기존의 연구들이 discretization에 집중했다면, anomaly score를 활용해서 continuous contrast set을 생성하게 된다. 실제로 개발자들이 사용하는 형태는 어떤 feature가 얼마나 statistically significant한지를 score로 확인함으로써 crash의 root cause를 좀더 쉽게 알아낼 수 있도록 한다.
- Paper link : https://arxiv.org/pdf/1911.04768.pdf
[2] Automatic Abnormal Log Detection by Analyzing Log History for Providing Debugging Insight
(Industrial Track) Samsung Research, Electronic에서 진행한 연구로써 IoT environment에서 생성된 test log의 history를 분석해서 각 log line의 importance와 noise score를 계산하고, 실제로 debugging insight를 제공하는 로그 라인을 하이라이팅하여 개발자에게 제공한다는 아이디어다.
[3] Explaining Regressions via Alignment Slicing and Mending
이 논문에서는 working code에서부터 발생하는 regression fault에 집중한다. 이런 fault를 디버깅하기 위해서는, correct version과 regresssion version을 비교하면 될 것 같지만 두 가지 challenge가 존재한다.
(1) Isolate the failure-inducing changes (2) Explain how the failure-inducing changes lead to the final observable failure
failure-inducing change의 minimal set을 구하기 위해 사용되는 방식이 program, 또는 input을 slicing하는 것이다. 기존의 dynamic slicing이나 delta debugging의 scalability, inaccuracy, non-explainability 등의 문제를 해결하기 위해서, root cause에 좀더 집중한 Alignment slicing & Mending이라는 방법을 제시한다. program code가 아닌 execution trace를 활용함으로써 regression bug가 root cause로부터 어떻게 manifestation point까지 전파되었는지를 설명할 수 있다. correct version의 trace와 regression trace를 align하고 (기존에 있던 trace alignment technique + 새로운 relaxation technique) causality graph를 생성하여 trace를 따라 ‘달라진 trace의 cause’를 제시함으로써 failure가 어떻게 전파되었는지를 ‘설명’할 수 있게 된다.
- regression bugs vs. normal bug localization: regression bug에 대해서는 기존의 FL에서 추가적으로 취할 수 있는 ‘correct version’의 정보가 있기 때문에 localize하기가 더 쉬울 것이다. 하지만 이마저도 correct version과 regression version이 change에 failure 발생과 무관한 변경이 포함되어 있기 때문에 trivial한 task는 아니다. (그러면 일반적인 FL에서 bug-inducing commit에 대한 명확한 정보가 추가되면 regression bug와 똑같이 다룰 수 있을까?: 버그가 나중에 발견되었다는 것은 이 버그를 detect하는 테스트가 그제서야 추가되었다는 뜻이고 (regression fault는 원래부터 bug detect test가 존재함), 버그가 발생한 커밋과 발견한 커밋의 사이가 멀어질수록 change의 양도 늘어나기 때문에 단순히 history의 diff를 뜨는 것으로는 root cause를 그리 쉽게 찾아낼 수 없을 것이다. 뒤에서 소개할 HSFL은 spectrum의 개념을 도입하고 기존의 SBFL과 결합함으로써 성능을 꽤 향상시켰다)
[4] Historical Spectrum based Fault Localization
역시 journal-first 논문인데, 실제 debugging practice에서 자주 사용되는 git bisect의 과정을 automation해서, bug-revealing test가 처음 fail하는 bug-inducing commit을 찾고, tangled commit 문제를 해결하기 위해 historical spectrum(Histrum)이라는 새로운 개념을 도입하여, bug-inducing change만을 걸러내고자 한다. (bug-inducing commit에 의해 변경되었지만, non-inducing commit에 대해서는 자주 변경되지 않은 부분의 suspicious score를 높게 할당)
[5] Empirical Assessment of Multimorphic Testing
Deep Learning System Testing
[1] Importance-Driven Deep Learning System Testing
(technical track)
- Official Website: https://deepimportance.github.io
Deep Learning System을 테스팅하는 데에 있어 testing adequacy criteria를 어떻게 설정할 것인지에 대한 논의가 꾸준히 있어왔다. 이번에 소개된 논문은 neuron의 causality를 기반으로 한다는 점에서 관심이 갔다. pre-trained DNN을 사용하여, training set을 사용하여 internal neuron 간의 contribution을 측정하게 된다.
결과적으로 clustering을 통해 important neuron의 cluster들이 만들어지고, 더 다양한 cluster들의 combination을 포함할수록 coverage가 높다고 판단할 수 있다.
coverage를 결정하는 과정은 크게 세 가지 step으로 이루어지는데,
(1) Neuron Importance Analysis
Deep Learning Model을 구성하는 뉴런들을 생각할 때, decision-making에 특별히 중요한 역할을 하는 뉴런들이 존재할 것이다. 각 뉴런의 importance를 어떻게 결정할 수 있을까? 아주 단순하게, 어떤 input x에 대한 각 layer의 output을 f(x)라고 할 때, f(x)를 decompose하여 이 결과에 이전 뉴런들의 contribution을 계산할 수 있을 것이다.
위의 MNIST input hitmap을 보면, 최종 classification decision에 대해 각 input feature로 사용되는 픽셀들의 중요도를 표현할 수 있음을 알 수 있다.
(추측: 아마 여기서 top-k important neuron을 고르고 이들을 기준으로 clustering을 수행하는 것 같다. 그러면 k는 어떻게 고르지?)
- 여기서는 layer-wise iteration을 수행하기 때문에 각 layer를 구성하는 neuron, Model에 input으로 들어가는 feature의 중요도를 지속적으로 tracking할 수 있다면 문제가 되는 input이 ‘왜 안되는지’ 설명하는 데에 도움이 되지 않을까? (input의 어떤 요소들이 결과에 많은 영향을 미치는지?)
(2) Important Neurons Clustering
-
Activation trace (vector of activation values from the training set - length가 전체 training set의 사이즈인 vector)를 k-means algorithm으로 clustering해서, group을 만든다. 왜 clustering을 하는 것일까? bucket 기반으로 activation value range를 grouping하는 k-multisection neuron coverage 같은 경우 bucket의 갯수와 그 range에 크게 영향을 받을 수밖에 없는데, clustering과 같이 dynamic하게 grouping을 하는 경우에는 각 neuron의 semantically different feature을 사용하기 때문에 좀더 adaptive한 set들을 얻을 수 있을 것이다. clustering을 함으로써 cyclomatic complexity를 낮추고 practical한 coverage 척도를 얻을 수 있는 것이다.
-
Cyclomatic Complexity: 소스 코드의 복잡도를 나타내는 metric, 프로그램의 제어 흐름을 graph, node, edge로 표현하고 (E(G) - N(G) + 2)의 간단한 계산식을 사용해서 표현할 수 있다.
-
형성되는 클러스터는 각 important neuron에 대해, activation value range로 표현될 것이다.
(3) Importance-driven Coverage
각 input에 대해서 INCC(Important Neurons Cluster Combinations) 벡터를 구하고, INCC value가 기존 test suite input에 대해서 새로운 feature (새로운 important neuron + activation value cluster 조합)을 도입할수록 IDC(Importance-driven Coverage)는 올라간다.
-
How can
DeepImportanceimprove DNN testing practice?: Important neuron들을 identify하고, 이들을 얼마나 ‘다양하게’ cover하는지에 대한 adequacy criteria를 제공함에 따라서 semantically-diverse test set generation이 가능하다. 기존의 attack strategy로 생성된 adversarial example 중 어떤 것들이 실제로 semantic diversity를 도입하는지에 대한 -
Q. 단순히 엄청나게 많은 Adversarial example들을 새롭게 모델에 feeding해서 retrain한다고 해서 성능이 높아질까? 오히려 낮아지는 경우도 있을까?
-
Cleverhans: Adversarial example들로 DL system들을 benchmarking할 수 있는 Python Library라고 함
-
Soundness에 대한 증명이 따로 있다. 즉, 새롭게 추가되는 input의 INCC가 기존에 cover되지 않아야만 IDC가 올라간다는 것. 여기에서 확인할 수 있다.
-
Input이 Semantically Different하다는 의미는 정확히 뭘까? noise를 추가하는 adversarial input이 semantic difference를 보장한다고 할 수 있을까?
Machine Learning for System
[1] Improving Vulnerability Inspection Efficiency Using Active Learning
- from Microsoft
- Security Bug: Needles in Heystack
- ML Approach: Low Cost, Low Accuracy → High Cost, High Accuracy
- Incremental SVM
- Human-In-The-Loop
- Considerations
- detect more, inspect less (loop)
- human error
- When to stop?
- training data labeling cost
- Why precision is not needed? (collect as much as we can)
[2] How Bugs Are Born: A model to identify how bugs are introduced in software components (extrinsic / intrinsic bugs)
[3] Quickly Generating Diverse Valid Test Inputs with RL
셋째날
삼일 째 정도부터 학회장 대신 모니터 앞에 덩그러니 앉아, 정신없이 지나가는 presentation을 따라잡으려 안간힘 쓰는 스스로의 모습에 약간 현타(…)가 오기 시작했다.
그래도 이번 학회를 통해 학계의 전체적인 연구 동향을 파악하고, 내 흥미를 이끄는 분야를 어느 정도 확립하겠다는 목표를 다잡으며 정리를 이어간다.
Regression Testing in CI
CI가 업계의 일반적인 practice로 자리잡으면서 Regression Testing으로 발견된 버그에 대해 online으로 root cause detection / localization / repair 하려는 노력이 새롭게 주목받고 있다는 인상을 받았다. 오늘의 세션은 좀더 근본적인 cost 측면에 집중해서 좀더 전통적인(?) 주제인 test selection/prioritization[1], 그리고 build cost optimization[2]에 대해서 이야기하고 있었다.
[1] Learning-to-Rank vs. Ranking-to-Learn: strategies for regression testing in continuous integration
Test selection/prioritization 문제에 machine learning technique을 적용한 연구들을 크게 learning-to-rank, 그리고 ranking-to-learn 전략으로 나눠서, RL을 포함해 다양한 ML 테크닉들을 비교한다. 실제 CI 환경에서 어떤 feature들이 성능에 영향을 미치는지를 파악하고 추후 이러한 ML 기반 알고리즘을 사용할 때 context에 따라 어떤 feature를 사용하고 튜닝할지에 대한 insight를 제공하는 것이 이 연구의 목표다.

Learning-to-rank algorithm은 test target들을 failure의 발생에 따라 서로 다른 class로 판별하는 classification, 또는 score의 regression 문제로 보거나 (pointwise, pairwise) 이미 label된 ranking을 직접 예측하도록 하는 regression 문제로 해석할 수 있다. (listwise)
미리 observe된 training dataset으로 모델을 학습하고, 추가적으로 CI가 돌 때마다 online으로 retraining을 하는 방법이 주로 사용된다고 한다.
반대로 Ranking-to-learn algorithm은 RL algorithm을 사용하여 항상 online으로 학습된다.
RQ를 보면 크게 (1) code characteristics, (2) CI process characteristics 두 가지의 측면에서 feature 각각의 중요성, inter-commit time과 같은 CI의 각 cycle의 특성에 따른 변화를 확인하고자 했고, selected ML algorithm들이 동일한 CI 환경에서 얼마나 효율적으로 prioritization을 수행했는지 비교하는 것 또한 주요한 contribution이다.
[2] A Cost-efficient Approach to Building in Continuous Integration
SmartBuildSkip이라는 tool 이름에서부터 유추할 수 있듯이, CI 코스트의 주요한 부분을 차지하는 build task를 최대한 줄이고자 하는 work이다. 우리가 관심있는 것은 failing build이기 때문에, 미리 build의 outcome을 예측하여, 확실히 pass할 것 같은 build들은 넘기고 가자는 것이다.
사실 결과를 미리 예측해서 skip 여부를 결정한다는 게 주객전도(?) 같은 느낌일 수도 있지만, CI의 대부분의 build는 pass할 것이고 (가설 1), fail이 한번 일어나면 연속적으로 fail이 더 일어나는 경향을 가진다(가설 2)는 직관을 가지고 제안한 것이 SmartBuildSkip이다. 이 가설은 저자들의 empirical study로부터 수립된 것.
Failure의 종류를 first failure와 subsequent failure로 나눔으로써, 기존의 build-prediction approach(ex. HW17)들이 단순히 모든 build들의 history를 동일하게 보고 예측했던 것보다 높은 정확도를 얻을 수 있다는 것이다. (build의 패턴을 고려하여 예측 결과를 생성) 즉, first failure에 대해서만 prediction을 수행하고, failure가 연속될 것이라는 가정 하에 passing build가 나올 때까지 항상 build를 실행하게 된다.
Random classifier를 사용해서 first-failure를 predict하고, 같은 project의 정보만을 사용하는 within, 다른 프로젝트의 feature와 함께 학습하는 cross (targeting cold-start problem) 두 가지 variant에 대한 결과를 함께 내놓았다. correlated feature의 경우에는 build feature에 해당하는 source, file, test churn(the number of changed source lines), distance from last failure, build가 요청된 시간(새벽에 build되면 fail 확률이 더 높다는 가정..?) 등을 사용했고, project-specific한 feature로 프로젝트의 규모와 얼마나 오래되었는지, test density를 사용했다. (거의 JIT DP와 비슷하다)
만일 fail하는 경우에도 잘못된 prediction (false negative) 때문에 build를 skip하게 되면 failure detection이 delay될 것이다. 논문에서 리포트한 결과로는 15%의 failing build들이 1 build 지연되는 정도라고 했는데, 1 build가 지연된다는 것은 결국 다음 commit, 또는 PR이 submit되기를 기다려야 하기 때문에 적은 cost라고 할 수는 없을 것이다. 이 부분에 대한 질문이 Q&A 세션에서도 많이 나왔던 것 같다.
Robustness of Deep Learning System
[1] Fuzz Testing based Data Augmentation to Improve Robustness of Deep Neural Networks
Adversarial example을 그대로 만들어서 DNN에 train 시킨다면 어떤 결과가 일어날까? 단순히 DNN이 이러한 adversarial input에 대해서도 잘 평가하는 더 robust한 model이 만들어질까?
기존에 test-based program synthesis에 대한 연구들에서 제기된 over-fitting 문제처럼, input set이 program behavior에 대한 specification 모두를 대체할 수는 없다. Data Augmentation을 기존 test generation technique에서 보던 것처럼 기존의 specification을 보완하는 형태로 생각한다면, 원래 있던 training set과 adversarial input들을 적절히 조합해서 ‘최적의’ training set을 찾으려는 시도가 가능할 것이다.
기본적인 아이디어는 mutation-based fuzzing을 DNN에 대해, (adversarial) input generation에 적용하는 것이며, 만들어진 mutated input들 중에 GA를 사용하여 loss를 최소화하는 optimal augmentation을 찾게 된다. 추가적으로 Selective Augmentation을 통해 이미 모델이 confidence를 가지고 (loss threshold, classification result) 예측하는 결과에 대해서는 새롭게 train 하지 않도록 한다. Selective Augmentation을 사용한 것과 하지 않은 것을 비교하여 evaluation을 수행한 결과도 있는데, selective augmentation을 켰을 때 accuracy가 살짝 <1% 감소하기는 하지만 training time 측면에서 30%의 시간 절약을 보여주었다.
Fitness function으로 loss를 사용하는 것은 단순하면서도 효과적인 방법이지만, coverage를 높이는 방향으로 새로운 input을 sampling하는 것 또한 고려해볼 수 있다. 논문에서는 Neuron Coverage를 fitness function으로 이용하여 얻은 accuracy 결과를 리포트하는데, 거의 비슷한 결과를 보였다. 하지만 training time이 50% 이상 증가하기 때문에 loss-based를 유지하는 것이 fuzzing에는 좀더 나은 선택일 것이다. (comment: 그럼에도 다른 coverage metric이나 좀더 다양한 confidence에 대한 measure을 시도해 보는 것이 유의미하기는 할 것 같다)
Testing & Debugging
Debugging을 할 때 우리는 어떤 input이 어떤 program element에서 문제를 일으켰는지 찾는다. input의 어떤 부분과 특정 program element의 interaction이 버그를 일으키는지를 찾는 것이 궁극적인 목적일 것이다. (이전에 봤던 Causal Testing에서도 특정 input의 어떤 영역이 fault를 일으키고, program element의 어떤 부분이 달라지는지를 함께 찾았다)
지금까지 든 생각은 Fault를 Localize하는 것에 있어 지금껏 faulty input과 faulty program element의 관계성에 그리 집중하지는 않았던 것 같다. 물론 program element 내에서 절대적으로 fault의 존재를 결정할 수 있고, input은 이를 발견할 수 있는 program path를 결정하는 역할이기 때문에 둘을 분리해서 생각하는 것이 크게 문제되지 않을 수도 있다. 하지만 실제 debugging practice를 생각해 보면, 우리가 이 input이 왜 문제가 될 수 있는지부터 생각하기 때문에, input 자체의 context와 faulty element의 location가 어떻게 correlated되어 있는지 판단할 수 있다면 좀더 효과적인 디버깅이 가능하겠다는 (약간 성급한) 결론이 났다.
[1] Debugging Inputs
-
Target Problem: Fault가 program code가 아니라 input 자체에 있을 수도 있을까? specification에 포함되지 않는 invalid input이 바로 그런 예시일 것이다. 이 논문은 그런 corrupted data를 program이 processing할 수 있는 형태로 고치려는 시도에서 출발한다. Program analysis를 사용하지 않고 black-box approach로 input repair을 접근했다는 점이 독창적인데, delta debugging에서 착안하여 (방식은 같지만 목적은 반대) invalid input fragment를 빠르게 찾아내고 동시에 content를 최대한 보존하는 input을 만들어내는 것이다. 이러한 approach를 delta debugging(ddmin)의 반대인
ddmax라고 이름붙였다. -
Invalid input in the wild: 실제로 JSON, Wave. OBJ 파일이나 DOT 파일을 input으로 사용하는 경우에서, input 자체가 문제가 되는 경우가 얼마나 있는지 확인하기 위한 empirical study를 먼저 진행했다. 제시한 경우들을 보면 input 자체가 따라야 할 Grammar이 있는 형태들인데, lexical 버전의 ddmax의 경우에는 input의 grammar check를 하지 않고 단지 program exit status만을 feedback으로 활용하여 passing input의 maximum subset을 찾는다. (그런데 논문에는
ANTLER자체에서 제공하는error recovery strategy를 활용한다고는 되어 있다. 그러고 나서 edit distance 등으로 원래의 failing input과 얼마나 다른지를 계산한다고 하는데..) syntactic ddmax (like tree delta debugging)의 경우에는ANTLR을 이용하여 input의 초기 AST 상태를 파싱하기는 하지만, 여전히 repair 과정에서 Grammar에 대한 정보를 사용하지는 않는다. -
Lexical Repair vs. Syntactic Repair Lexical Repair은 input을 단순히 sequence로 보고 나누는 반ㅁ년, Syntactic Repair은 기본적으로 input을 structure로 파싱해서 tree 단위로 delta debugging scheme을 적용한다.
-
Evaluation: 실제로 ddmax가 얼마나 input을 많이 고칠 수 있었는지에 대해서는, real-world crawling example과 이들에 mutation을 해서 만들어낸 추가적인 데이터에 대해서 실험했다. syntatic하게 input의 AST를 만들어서 repair를 수행한 버전이 가장 좋은 repair 성능을 보였다. (더 많은 passing input을 generate하기도 했고, 만들어진 data의 loss 측면에서도 더 좋았다)
모든 실험이 아마도 저자의 노트북일 Lenovo Thinkpad에서 이뤄졌다고 하는데, 생각보다 소박한 시스템(?)이라 인상에 남는다. 재택 근무 중이셨을까 (…)
[2] Which Variables Should I Log?
Logging할 때 어떤 variable을 tracking할 지 추천해 준다면 어떨까? logging할 때 한 가지 variable에 대해서만 생각하느라 자주 log statement를 수정하는 나로써는 굉장히 흥미가 당기는 질문이었다. 이미 존재하는 logging statement를 재료로 새로운 log statement를 추천해 줄 수 있지 않을까? 하지만 이러한 prediction task가 쉽지는 않다. 두 가지 이유 때문인데, 1) different labels: 서로 다른 logging statement마다 타겟으로 하는 variable이 다르고, 그에 해당하는 label도 다를 수밖에 없다. 2) OOV words: program token, identifier들은 단순히 natural language의 vocabulary와는 다르다. 수많은 가능한 단어들이 존재한다.
이러한 두 가지 challenge를 극복하고자 multi-label classification problem 대신 representation learning problem으로 접근한다. logging statement 주변의 코드 snippet을 RNN encoder에 통과시켜서 적절한 representation을 배우도록 하고, 두 번째 단계로 이 representation을 binary classifier에 통과시켜서 (로깅할지, 말지) 둘 중 하나를 선택하게 하는 것이다. 직관적으로 보면 각 token이 해당 프로그램 스니펫에서 어떤 역할을 하는지를 먼저 representation으로 배운 다음에, 이렇게 정제된 정보 위에서 logging을 해야 할지 말지에 대한 classification을 수행한다는 아이디어가 representation의 활용을 현명하게 한 예시(?) 같아서 굉장히 마음에 들었다.
-
novel method for mapping program tokens into word embeddings: making use of pretrained word embeddings of natural language tokens - 아직 이 과정에 어떤 novelty가 있는지 깊게 살펴보지는 못했지만, 역할을 표현하는 데에 natural language token이 과연 필요할까? 에 대한 의문이 들었다. 내가 생각한 방향과 논문이 생각한 방향을 비교해 볼 것.
-
representation learning: 학습 데이터가 굉장히 복잡하고 큰 dimension을 가지고 있더라도 깊고 방대한 neural network를 통해 데이터의 선형 분리가 가능한 형태의 representation을 도출할 수 있다는 것.
[3] Boosting Automated Program Repair with Bug-Inducing Commits
(NIER: New Ideas and Emerging Results) 이전에 Historial Spectrum based Fault Localization의 저자인 Ming Wen 씨가 APR에 대해서도 멋진 아이디어를 꺼내놓았다.
search-based patch generation에서는 ingredient space와 mutation operator를 어떻게 정의하는지에 대한 결정을 통해 search space가 정의된다.
지금까지 해당 프로젝트 자체의 history에서 생성된 patch와 다른 프로젝트들에서 수집된 patch들의 fixing pattern들을 학습하여 이들을 정의하는 방법들이 제시되었지만, 여기서는 버그가 어떻게 ‘fix’되었는지가 아니라 bug가 어떻게 ‘introduced’되었는지를, bug-inducing commit의 정보를 통해 학습하는 것이 효과적이라는 것을 보인다. preliminary approach는 bug-inducing commit으로부터 도출된 fixing ingrediant와 mutation operator들을 사용하여 APR을 수행한 결과 기존 테크닉들이 고치지 못한 11개의 버그에 대한 패치를 새롭게 찾아냈다고 한다. NIER 트랙으로 paper가 공개되어 있지 않아서 테크니컬한 detail은 알 수 없어 아쉬웠다. 실제로 bug-inducing commit으로부터 ingrediant와 mutation operator를 어떻게 만들어낼 수 있는지에 대한 과정을 명확하게 알고 싶다.
[4] Cooperative API Misuse Detection Using Correction Rules
마찬가지로 NIER 트랙에 소개된 논문인데, API misuse로 인한 bug를 특정한 대상으로 삼은 것에 관심이 갔다. API usage에 대한 specification을 infer하고 misuse를 detect하고자 하는 기존의 테크닉들은 여전히 큰 false-positive rate 때문에 상용화하기에는 무리가 있는 단계다. 이 논문에서는 개발자들이 manual하게 detect하고 fix한 해당 API misuse에 대해서 correction rule을 infer 하고, 다른 프로젝트에서도 동일하게 해당 API를 쓰는 경우에 대해 적용할 수 있도록 한다. knowledge transfer의 관점에서, 여러 프로젝트에서 공통으로 사용되는 API misuse에 대한 버그를 접근한다는 점에서 의미있는 방향인 것 같았는데, correction rule이 얼마나 general한지 (어떤 형태일까? 단순한 patch일까? 아니면 patch의 template일까?), 어떻게 이 rule을 infer할 수 있는지 (learning-based patch generation 처럼 seq2seq model이나 predefined rule에 대한 classification일까?)가 더 궁금했다.
[5] Seenomaly: Vision-Based Linting of GUI Animation Effects Against Design-Don’t Guidelines
Linting의 범위를 GUI Animation으로 확장했다는 점에서, 꽤 명확하고 재미있는 접근이라고 생각했다. card movement, menu slide in/out, snackbar display 등등 이렇게 말하면 안 와닿을 수도 있지만, 프레젠테이션에서 모아놓고 보니 평소에 아 올드하다.. 정신없다.. 라고 생각했던 각종 안티패턴들을 쉽게 떠올릴 수 있었다. 놀랍게도 제발 이렇게 만들지는 마!! 라고 되어 있는 Don’t guideline이 따로 있다고 한다. (Android Material Design Guideline) 이것만으로는 데이터가 부족하기 때문에 VAE(Variational AutoEncoder)와 GAN을 함께 사용하여 다양한 don’t example들을 synthesize했다. 여기서는 linting을 위한 실제 classification task에 집중하기보다는 unlabelled GUI animation을 grouping하여 dataset을 만들어내는 것에 집중했다.
-
GUI Animation features: vision-based feature extractor를 사용하여 unlabelled GUI animation들에 대한 temporal-spatial feature를 훈련시킨다. 이 과정은 unsupervised로 이뤄진다. 그리고 이렇게 학습된 feature들을 바탕으로 명확한 don’t guideline의 경우, 그리고 이들의 linted 버전을 feature space에 위치시킨 후 KNN classification을 수행하게 된다. 즉, 타겟 애니메이션의 k-nearest neighbors중 몇 개가 don’t guideline에 속하는지 아닌지를 판단하여 classification을 수행하게 된다.
-
Comment: 최근에 Code Reusability에 대한 문제를 건드려 보고 싶어서, application의 실제 internal logic과 연관되는 GUI component를 추출하는 것에 대해 program slicing 측면으로 생각을 했었다. 여기서는 linting의 측면에서 GUI animation의 특성을 classify하는 문제이기 때문에 내가 생각하던 target problem과는 조금 다르지만, GUI component의 visual semantic을 feature extractor로 뽑아내고 clustering을 수행하는 아이디어에서 어느 정도 영감을 받을 수 있을 것 같다.
[6] Testing File System Implementations on Layered Models
갑작스레 GUI에서 low level로 내려와 system call sequence에 대해서 논의하게 되었다. (나의 관심사란 대체 무엇인가..) 파일 시스템을 테스트하기 위해 다양한 system call sequence를 input으로 robustness를 평가할 수 있을 것이다. (이런 점에서는 GUI를 테스트 하기 위해 event sequence를 generate하는 것과 동일하다)
이 연구는 파일 시스템과 같이 여러 layer로 분리된 복잡한 전체 시스템을 테스트하고자 한다. layered model checking이라고 이름붙인 이 개념은 먼저 전체 abstract한 모델에 대한 abstract workload를 먼저 생성하고 layer by layer로 이를 concrete한 system call sequence로 확정하는 단계를 거친다.
Defect Prediction
[1] The Impact of Mislabeled Changes by SZZ on JIT Defect Prediction
- JIT defect prediction: 어떤 change가 일어났을 때 바로, 이 change가 defect를 내포할 수 있는지 바로 판단할 수 있다면 얼마나 좋을까?
그러기 위해 먼저 어떤 bug의 원인이 되는 change가 어떤 commit에서부터 비롯되는지 알아야 할 필요가 있다. (bug-inducing commit) 기존에 제안된 SZZ algorithm(bug-fixing commit의 changed line에서부터 candidate commits들을 observe하는 방식)에 많은 noise가 있음이 밝혀졌고 SZZ algorithm으로 만들어진 데이터를 JIT defect prediction model을 train할 때 사용하는 것은 결국 모델 자체의 부정확성에 큰 영향을 미칠 것이다.
이 연구에서는 이렇게 mislabeled bug-inducing change들이 실제 JIT defect prediction model의 성능에 얼마나 큰 영향을 미치는지를 확인한다.
4가지의 SZZ variant (B-SZZ, AG-SZZ, MA-SZZ, and RA-SZZ)에 대해서 evaluation을 수행하는데, 그 결과 RA-SZZ가 가장 mislabeled change를 적게 만들었다고 한다.
실제로 Defect Prediction Model에 들어가는 feature 중 중요하게 작용하는 것이 한 change에서 변경된 파일의 갯수와 같은 statistical한 metric인데, 이런 것들은 SZZ algorithm의 mislabeling으로부터 만들어진 noise에 크게 영향을 받지 않았다고 한다. 하지만 그 다음으로 중요한 metric에 대해서는 noise의 영향을 어느 정도 받았다고 한다.
[2] Understanding the Automated Parameter Optimization on Transfer Learning for Cross-Project Defect Prediction: An Empirical Study
Software Development
[1] Improving the Pull Request Review Process Using Learning-to-rank Algorithms
개인적으로 Review process가 협업을 중심으로 한 소프트웨어 개발 사이클에서 굉장히 중요한 역할을 차지한다고 생각한다. 하지만 막상 내가 리뷰어가 되어서 누군가의 코드 리뷰를 하기란 굉장히 귀찮은 일(…)이 되고 만다.
결국 리뷰의 결과는 이 Pull Request를 Merge할지, 말지가 되는 것인데 단순히 이를 binary classification 문제로 본다면, 잘못된 prediction으로 인한 cost도 굉장히 클 것이고, 여기서 소개하는 연구는 현재 열려있는 전체 pull request들에 ranking을 매기고자 한다. (가장 빨리 리뷰할 수 있는 것부터 추천) 이렇게 Learning-to-Rank 모델을 이용해서 기존의 classification 기반 decision prediction을 보완할 수 있을 것이다.
LtR 모델에 들어가는 metric들은 총 18가지인데, Source Code Metrics, Textual Information Metrics, Contributor’s Experience Metrics 등이 있다.
- 기존의 LtR 알고리즘들: ListNet, RankNet, MART, random forest
Keynote: Formal Reasoning and the Hacker Way - Peter O’Hearn
Program을 Reasoning한다는 것은 무슨 뜻일까? 이번 학기에 논리학 개론을 듣기는 했지만 이런 formal한 정의와 표현들을 어떻게 Static analysis에 활용하는지는 연결하지 못한 탓에, 테크니컬한 디테일에 대해서는 조금 어렵게 느껴졌지만, 전체적으로 Facebook에서 사용되는 static analyzer를 deploy하고자 하는 과정에서 얻은 insight는 practice에서 formal reasoning과 hacker way가 어떻게 결합하여 시너지를 낼 수 있는지 이해하는 데에 굉장히 유용하다고 생각했다.
Theory Hacking에 대해서는, 너무 엄밀함을 추구하기 보단 최종 static analyzer의 cost를 생각해서 disjunction들을 drop하고, 탐색하는 path를 undersampling할 수 있었다는 Hacky한 자신의 접근을 얘기하며 “No, I’m not a bad person!!” 하고 항변하시는 모습이 재미있었다 ㅎㅎ
넷째날
넷째 날의 Technical Track에서는 meta-model, 혹은 특정한 rule을 정의하여 코드를 자동으로 생성하고 correctness를 verify하는 테크닉에 관한 Code Generation and Verification, 프로그래밍 개발과 유지 보수에 있어서 꼭 필요한 버전 컨트롤 시스템의 다양한 Practice와 문제점들을 해결하는 Version Control and Programming 세션과 같은 ecosystem 분야에 흥미가 갔다. 이어진 Testing and Debugging 세션에서도 재미있는 주제들이 많이 나왔는데, Fuzzing 관련해서는 greybox technique들을 중심으로 발전한 형태들이 있었고, security rationale에 대한 empirical study, JIT DP의 cross-project learning, 또는 cross-project로 transfer learning을 활용한 bug localization, continuous integration의 cost에 대한 연구들이 소개되었다.
코드 주변의 컨텍스트를 활용하여 유추하고자 하는 부분의 statement나 expression을 자동으로 생성할 수 있는 테크닉들에 관심이 갔는데, 그 중 하나가 On learning meaningful assert statement과 같은 페이퍼였고, 이전에 살펴보았던 bug patch를 자동으로 생성하는 테크닉들과 비슷한 전략으로 다양한 code completion task를 수행할 수 있을지 궁금해졌다.
Code Generation and Verification
Co-Evolving Code with Evolving Metamodels
Model-driven development 패러다임에서 모델의 변화와 이로부터 구현하는 실제 코드의 co-evolution을 자동화시키는 것에 대한 연구가 소개되었다. UML과 같은 메타 모델이 변화했을 때 그 변화를 자동으로 캡쳐해서 기존에 구현된 코드에 자동으로 적용되고, 개발자가 이를 verify하는 과정을 포함한다.
- impact analysis: 실제로 코드를 변경하기 전에 impact analysis를 수행하게 되는데, Change interface를 정의해서 단순한 addition, removal, modification에서부터 이들의 sequence로 이루어진 complex change까지를 커버한다. 중요한 것은 metamodel에서의 change가 1:1로 매핑되는 것이 아니라 코드 레벨에서 n개의 change와 매핑될 수 있다는 점이다. 예를 들어
Property라는 class가 실제로 코드에서는Property와PropertyImpl로 생성되는 것처럼 말이다. 이때 최대한 정확하게 metamodel의 한 가지 change가 code에 몇개의 impact를 미치는지 identify하는 것이 이 연구에서 제시하는 impact analysis 기법이다. - It proposes the appropriate resolutions that can propagate the impacting change
- Evaluation: 실제 metamodel의 evolution에 의해 영향을 받는 부분을 얼마나 효율적으로, 그리고 정확하게 알아낼 수 있을지에 대한 질문과, 실제로 그렇게 영향받는 부분에 대한 resolution의 정확도에 대한 평가, resolution이 틀릴 때에도 어느 정도 의미있는 (개발자들에게 유용한) 정보를 제공할 수 있는지를 확인했다. 메타모델의 변화에 대해서 영향받는 클래스의 갯수는 0개-47개의 다양한 범위를 갖고 있었고 여러 프로젝트에 걸쳐서 코드 수정이 일어나게 되는 것을 확인할 수 있었다. (impact analysis의 중요성) 몇 가지 프로젝트를 제외하고는 거의 정확한 resolution을 생성할 수 있었다. (precision, recall > 90) 다만 mismatch하는 몇 가지 경우에서는 delete에 대한 경우였는데 제안된 resolution의 경우에는 해당하는 부분을 지우는 것이 아니라 move나 rename으로 대체된 경우였다.
Code Artifact Analysis
An Empirical Validation of Oracle Improvement (Journal First)
이 연구의 전신은 OASIS라는, 각 테스트 케이스에 존재하는 oracle의 오류를 감지하고 iterative하게 오류를 fix하는 human-in-the-loop approach이다. 이전 work에서는 1저자가 직접 oracle improvement feedback loop에 참여해서 evaluation을 수행했지만, 좀더 이 프레임워크의 유용성을 명확히 확인하기 위해 68명의 participants를 모집하여 human study를 진행한 결과를 리포트한다.
- OASIS 논문: Link
자동으로 Test Case를 생성해주는 테크닉의 명확한 bottleneck은 어떻게 해당 input에 대한 oracle을 함께 제공하느냐인 것인데, Randoop이나 Evosuite과 같은 통상적인 Test Generation Tool은 fine-grained semantic bug를 탐지한다기보다는 단순히 타입 또는 특정한 edge case만을 개략적으로 다루게 되는데, 이것이 자동 생성된 테스트 케이스의 quality를 저하시키는 주요한 요인이 되어왔다. test adequacy에 대해서는 coverage와 다양한 search-based, symbolic execution technique을 통한 quality measurement가 제안되어 왔지만, 상대적으로 oracle에 대해서는 평가 또는 개선을 위한 methodology가 부족한 것이다.
참고: “Oracle Problem” - how to define accurate oracle, capability of detecting faulty behaviours exercised during testing
Oracle의 performance를 정의하는 속성은 크게 두 요소, 즉 completeness (correct behavior인데 fail하지는 않는지 - false positives), soundness (wrong behavior인데 pass 하지는 않는지 - false negatives)로 나눌 수 있을 것이다. OASIS에서는 이미 존재하는 oracle을 validate+improve하기 위해 false positives에 대해서는 추가적인 search based test case generation을 사용해서, false negatives에 대해서는 mutation testing을 이용해서 각 케이스들의 counterexample들을 만들어내게 된다. (OASIS 페이퍼를 아직 읽어보지는 않았지만, 현재 프로그램에 대해 fail하는 test case에서는 또다른 input 생성 + 같은 oracle 조합으로 correct한 input-output인데도 fail하는 것이 있는지 찾고, pass하는 test case에서는 mutant들을 사용해서 이 oracle이 mutation에 의해서 생긴 misbehavior를 놓치지는 않는지 체크하는 것으로 추측했다 - 나중에 읽어보고 이 추측과 비교해볼 것)
이번 empirical study에서는 iterative oracle improvement의 효용성을 검증하기 위해, manual하게 oracle을 고치는 것과 비교해서 얼마나 많은 cost가 절약되는지, 몇 번의 iteration 끝에 correct oracle을 생성해낼 수 있는지를 알아본다.
- A novel human study on oracle assessment
- A novel human study on oracle improvement
Is Static Analysis Able to Identify Unnecessary Source Code? (Journal First)
소프트웨어의 개발 과정 속에서는 필연적으로 더 이상 필요하지 않은 코드들이 생긴다. 하지만 더하는 것보다도 어려운 것이 빼는 것일 터. 그렇게 개발자들은 더이상 쓰이지 않는 코드들을 차마 버리지 못한 채 (언젠가 쓰이겠지 하는 잘못된 믿음으로) 남겨놓고는 한다. 이렇게 남겨진 코드들은 저장 공간을 잡아먹을 뿐만 아니라 코드의 가독성과 migration, 검증 과정을 방해하는 골칫덩이로 남게 된다.
Production environment에서 수집된 execution information을 활용하는 방법도 있지만, 여기서는 static analysis로 어디까지 갈 수 있는지에 집중한다. ‘code stability’와 ‘code centrality’의 특성에 기반해서 말이다.
Unnecessary code != dead code
중요한 건 항상 필요 없는 코드가 ‘아예 실행이 되지 않는 코드’와 동치는 아니라는 점이다. 실행은 되지만 프로그램의 실제 behavior와 관계 없는 코드들이 있을 수 있고 (안 쓰이는 variable assignment, 출력문 등등), 이런 것들까지 포함하기 위해서는 단순한 reachability analysis 그 이상이 필요하다.
(need heuristic - 코드의 change history를 고려한 metric인 stability, 다른 시스템 요소들이 해당하는 코드 영역에 얼마나 의존하고 있는지 여부에 대한 centrality information를 사용하게 된다. 자세한 technical detail을 더 확인할 필요 있음: Journal Paper Link)
실제 evaluation에서는 recommendation 중 34% 정도가 실제로 개발자들에 의해 필요 없는 코드로 확인되었다고 한다. Static analysis가 개발 과정에서 quick feedback으로 작용하면서 유용할 수 있다는 것인데, 사실 false alarm 문제를 완전히 해결한 것처럼 보이지는 않기 때문에 어떻게 이를 더 refine할 수 있을지 살펴볼 필요가 있다.
Version Control
Planning for Untangling: Predicting the Difficulty of Merge Conflicts (Technical)
Merge Conflict는 버전 컨트롤 시스템에서 어쩔 수 없는 골칫거리다. 물론 운 좋게 몇 부분의 change만 확인하고서 conflict resolve가 가능한 경우도 있지만, 하나를 고치면 그 다음에 다른 conflict가 생기고, 또 다른 conflict가 생기고.. 이런 경우를 맞닥뜨리면 merge를 포기하고 거의 매뉴얼하게 change를 apply 해야 할 때가 있다.
여기서는 merge가 얼마나 어려울지 먼저 예상해 주는 꽤나 매력적인 테크닉을 제안한다. 이 conflict가 해결하는 데에 어려울지, 어렵다면 어떤 요소들 때문일지에 대한 정보를 미리 제공해줌으로써 개발자들이 여러 conflict들을 마주할 때 우선순위를 매길 수 있다.
이러한 예측을 위해 기존의 difficult merge conflicts(6,380 conflicts across 128 java projects)들의 특성을 파악하고 classification model을 학습시켰다. 여기에는 bagging과 같은 ML algorithm이 사용됐다.
Towards Understanding and Fixing Upstream Merge Induced Conflicts in Divergent Forks: An Industrial Case Study (SEIP)
Divering Forks란 프로젝트를 fork해서 오랫동안 upstream에 merge되지 않고 독립적으로 개발을 이어나가는 통상적인 Practice다. 이런 변경 사항들을 나중에서야 upstream으로 들여오려고 할 때 merge conflict가 빈번하게 발생할 수 있는데, 이 연구에서는 특별히 이런 경우에 대해서 industrial case study를 수행한 결과물이다. (Microsoft Edge 개발 시에 발생한 케이스들이다)
Merge conflict들을 textual conflict, build breaks, test failure의 세 가지 분류 체계로 나누고. 특히 build breaks에 대한 conflict들을 자동으로 고칠 수 있는지 여부에 대해서 파악하여 실제 Microsoft Edge Beta 개발에 사용된 build break merge conflict fix tool의 효과에 대해서 report한다.
Version Control Systems: An Information Foraging Perspective (Journal First)
- Journal 링크: IEEEXplore
버전 관리 시스템을 Information의 Source로 보는 시각이 흥미로웠다. 개발자들이 VCS에서 어떤 정보를 어떻게 찾는지에 대한 이전의 empirical study를 바탕으로 이 연구에서는 Information Foraging Theory를 사용하여 기존 empirical study에 추가적인 insight를 더한다. Information Foraging Theory는 인간이 정보를 검색할 때 원시 동물적인 ‘먹이 채집 메커니즘’을 따른다는 재미있는 관점인데, Information scent, Information diet와 같은 기본적인 가정에서부터 information foraging model을 구축하게 된다. 즉, commit들의 리스트를 information environment로 보고, 이 commit 내부에 존재하는 bug의 location이 seeking하고자 하는 정보가 되는데, 바로 버그를 찾는 개발자를 먹이를 찾는 하이에나로 보는 것이다 (…)
여기서 information을 찾는 데에 핵심적인 역할을 하는 cues와 scent는 커밋 메시지의 각 단어들과 그 단어들 사이의 similarity로 대응된다.
VCS에서 정보를 찾는 것을 3가지의 major foraging activity로 분류하여 (foraging for change awareness, specific commits, creating commits to ease future foraging) survey를 수행한 결과 개발자들이 중요하게 생각하는 requirements를 추출해내었고, 정보의 탐색 과정에서 장애물이 되는 요소들을 identify하기도 했다. 이를 통해 information foraging에 드는 cost를 정량화하고 개선할 수 있는 방향을 기존의 Information Foraging Theory에서 제안된 방법론을 적용하여 도출하게 된다.
실제로 debugging에 있어서도 주된 관심사가 어떻게 버전 관리 시스템의 과거 정보를 활용할 것인지이니만큼, 기존의 Information Theory의 관점을 가져와서, 커밋 기록을 어떻게 관리하고 정제할 것인지에 대한 전반적인 insight를 제공하는 유용한 work이었다고 생각한다. 다만 이러한 insight들을 실제로 VCS의 tangled, 혹은 fragmented된 change들을 관리하고 개선시키는 데에 어떻게 활용할지에 대한 설명은 조금 모호하게 느껴졌는데, ‘forageable information’을 정확히 어떻게 분류하고 이것들을 찾아내는 데에 어떤 concrete한 방식을 적용할 것인지에 대한 고민이 추가적으로 들어갈 여지가 있다고 생각했다.
Testing & Debugging
On Learning Meaningful Assert Statement for Unit Test Cases
이 논문 또한 test case generation에서 assertion oracle의 quality 문제를 짚어내는데, NMT 모델에 테스트 대상이 되는 메소드의 token 정보를 컨텍스트로 제공함으로써 좀더 의미있는 assert statement를 생성하고자 하는 것이 핵심이다.
전체적인 테크닉은 NMT 모델을 활용하는 것 외에 현재 테스트 메소드의 대상이 되는 focal method의 identification, across-project learning을 위한 token의 abstraction, 또는 copy mechanism의 사용 등으로 statement prediction의 정확도를 높였다.
manually generated된 assert statement들의 31%을 top-1 rank로 맞췄고, top-5에 대해 생각했을 때에는 50% 정도를 exact match로 맞췄다고 한다. test assert statement의 recommendation, code completion application에 대해 promising한 결과를 보여주었고, 이 approach를 좀더 practical한 영역으로 발전시키기 위해 보완할 수 있는 점이 궁금해지는 연구였다. (추가적인 program semantic verification, 또는 동일 test suite의 context 포함)
Deep Transfer Bug Localization (Journal First)
Deep-learning based bug localization에서 historical data를 사용하는 supervised approach들이 효율적이라는 것이 알려졌지만, Unavailability of sufficient bug data 문제로 인해서 한 프로젝트 내의 데이터만 갖고는 bug localization model을 학습하기가 어렵다. 이로 인해 cross-project bug localization의 필요성이 대두되었고, 여기에서는 deep transfer learning으로 접근하여 source가 되는 transferable semantic feature들을 추출하여 target project에 효율적으로 적용하고자 한다. 그 결과 각각 top 1, top 5, top 10 position 내에 30, 50, 60%의 버그들을 효율적으로 위치시킬 수 있었다. (SBFL이나 mutation-based FL보다도 좋은 성능인지 궁금)
A Benchmark-based Evaluation of Search-based Crash Reproduction
Crash report로부터 이를 reproduce할 수 있는 test case를 생성하는 과정을 automate하는 테크닉들을 평가하고 비교할 수 있는 벤치마크를 제시하는 연구다. (JCrashPack + ExRunner)
200개의 Java project stack trace로 구성된 JCrashPack을 통해 기존에 제안된 Crash reproduction tool인 EvoCrash에 대한 extensive evaluation을 수행하였고, Crash의 종류에 따라 (NullPointerException, IllegalArgumentException, ClassCastException, IndexOutOfBoundsException) reproducing의 난이도가 달라진다는 관찰 결과를 리포트한다. 또한 qualitative analysis를 통해 crash reproduction의 challenging한 포인트들을 리포트하는데, input data generation과 abstract/anonymous classes를 다루는 것들에 대한 것이었다.
An Investication of Cross-project Learning in Online JIT Software DP
- JIT DP: 주어진 software change가 defect-inducing인지 clean인지 ML classifier를 통해 결정
- training data가 많이 필요한 만큼 project의 시작에서는 좋은 성능을 내기 힘들다
- CP(Cross-Project) learning으로 이 문제를 풀려고 했지만 WP(Within-Project)보다 좋은 성능을 내지는 못했다. 그러나 실제 환경에서 CP로 처음 트레이닝이 되어 있더라도 지속적으로 들어오는 WP data로 classifier를 업데이트함으로써 성능을 높일 수 있을 것이라는 아이디어다.
- 즉, CP 데이터가 JIT DP의 online learning scenario에서 얼마나 useful할지에 대한 insight를 주는 데에 의미가 있는 논문이다.
- 3개의 ongoing project에 10개의 기존 mature한 프로젝트의 198469개 commit을 이용해서 CP data를 생성하여 적용했다.
- initial stage에서 WP classifier보다 54% 향상된 G-mean score를 보였고, 이후 트레이닝이 진행된 이후에도 classifier가 좀더 안정적인 prediction accuracy를 유지하도록 했다. (WP 데이터만 쓰면 중간에 prediction performance가 갑자기 급격하게 낮아지는 현상이 있었는데 이걸 줄였다)
An Empirical Study of Long Duration of Continuous Integration Builds
전반적으로 CI build cost에 대한 문제를 다루는 논문을 이번 ICSE에서 관심있게 봤던 것 같은데, 이 empirical study는 long build duration의 impact에 집중했던 과거 연구들과는 달리 long build duration을 일으키는 원인들을 파악해내는 데에 집중한다.
- Mixed-effects logistic models
- Common wisdom factors(project size, team size, build configuration size, test density) 외에도 더 있을까?
- 재미있는 발견: rerunning failed commands multiple times
-
cache의 사용으로 advantage를 볼 수 있다는 것 + configuration misuse로 인한 성능 저하가 많다는 점
-
Research Goal: 1283개의 프로젝트 (rails, jruby, openproject 등의 popular projects 포함) 에서 수집한 Travis CI build 정보를 담고 있는 TravisTorrent dataset을 활용, long build duration의 frequency와 long build duration에 영향을 미치는 중요한 factors와 그 관계를 파악하는 exploratory research를 수행했다.
- Main observation으로는 build failure을 줄이기 위해 failing command를 여러 번 실행하는 configuration option이 long build duration과 밀접한 연관이 있다는 것이다. 비록 rerunning을 통해서 build failure가 줄어드는 경우는 3% 정도밖에 되지 않았는데도 말이다. 부주의한 misconfiguration으로 인한 영향 외에, cache를 통해 줄일 수 있는 가능성을 report하며, 현재 CI 서버의 workload에 따라 delay를 예측하는 것이 유용하다는 finding도 함께 제공한다.
이 연구의 주제와 같이 (long build duration에 영향을 미치는 요인은 무엇인가?) 어떤 observation의 cause를 모델링하는 empirical study에서는 어떤 통계적이고 구조적인 methodology를 활용하는지에 대한 궁금증이 일었다.
-
Build duration variation을 통해 subject project를 결정: 단순히 build duration이 긴 프로젝트를 고르는 것이 아니라, high variance를 가지는 프로젝트를 선택함으로써 단순히 CI의 load 때문에 build가 길어지는 것이 아닌 케이스들을 추출한다.
-
Mixed effects logistic model: dependent variables(long/short build durations classification) + independent variables from data columns in TravisTorrent (ex. configuration files changed, caching, author experience)
-
Correlation Analysis: use spearman rank sigma clustering analysis (remove highly correlated variables)
여기서 각 factor들의 영향을 모델링하기 위해 사용된 mixed-effects logistic models는 fixed effects와 random effects를 함께 고려하는데, 해당하는 프로젝트마다 factor들의 영향이 다를 수 있기 때문에 traditional regression model과는 다르다. project마다 다른 intercepts를 고려하기 위한 term은 아래에서 theta_g로 표현하고 있다.

이러한 분석을 통해 나온 Finding들은 configuration에서 적절한 rerunning 횟수에 대한 중요성, caching의 유용성, unnecessary, duplicated test를 줄이는 것이 build duration을 줄이는 데에도 효과적이라는 사실을 통해 clone detection technique을 활용한 test optimization, prioritization이라는 research 방향도 함께 제시하였다.
Deep Learning Testing & Debugging
trader: trace divergence Analysis and Embedding regulation for Debugging RNN
RNN에 제공하는 word embedding은 textual input을 measurable한 numerical value로 변환하기 때문에 유용하지만, word embedding 자체가 problematic할 때에는 이를 detect하거나 다루기가 까다로울 수 있을 것이다. 이 연구에서는 model의 execution trace들을 비교하여 problematic embedding이 얼마나 모델 퍼포먼스에 영향을 미치는지 확인하고, 이를 fix하는 테크닉을 제공한다.
전체적인 과정은 correctly classified sample과 misclassified sample 사이의 divergence를 분석한 후 (using oracle machine and buggy machine), faulty state dimension을 찾아낸 후, 이 dimension 작은 purturbation들을 추가하여 word embedding을 retrain 시키게 된다. 즉, 모델이 ‘헷갈려’하는 subspace에 대해서 다양하게 mutated된 example들을 추가하여 retrain하는 것이다. Debugging feedback을 이용하여 RNN을 repair하는 첫 시도라는 점에서 꽤나 의의가 있고, 프로그램의 디버깅 테크닉의 기본적인 아이디어를 성공적으로 뉴럴넷에 적용한 시도라는 생각이 들어서 흥미로웠다. 다시 읽어보기
다섯째날
토요일까지 이어진 ICSE Technical Track이 종지부를 찍었다. Code를 Dynamic Language Model로 표현하여 Out-of-Vocabulary 문제의 해답을 제시한 논문, 그리고 이어서 Deep learning을 대상으로 한 testing & debugging 세션에서도 재미있는 주제들이 많이 소개되었다. Machine Translation 모델의 잘못된 결과를 metamorphic relationship을 통해 detect하는 Structure-Invariant Testing, 모델 자체를 고치는 것이 아니라 post-processing 과정으로써의 repair를 수행하는 것, Deep Nueral Network의 Repair에 있어 Fix Pattern과 Challenge를 소개한 Survey 논문도 있었다. 마지막으로 APR(Automated Program Repair) 분야에서는 Neural Net을 이용해 Fix Pattern을 모으고 주변의 컨텍스트를 활용하여 Code Transformation Learning을 수행하는 논문들이 괄목할 만한 성능을 보여주었다.
ICSE-10 Most Influential Paper Award
- Oracle-Guided Component-Based Program Synthesis: http://susmitjha.github.io/papers/icse10.pdf
ACM SIGSOFT Distinguished Artifact Award
- Primers or Reminders? The Effects of Existing Review Comments on Code Review
- 코드 리뷰 시에 다른 리뷰어에 의한 기존의 리뷰를 먼저 보는 것은 bias를 초래해서 객관적인 판단을 내리지 못하게 할 수도 있지만, 다른 리뷰어들의 관점을 참고하여 놓칠 수 있었던 부분에 주목하는 긍정적인 영향이 될 수도 있다. 이를 알아보기 위한 empirical study의 흥미로운 한 instance인 것 같다. 이곳에서 읽을 수 있다.
Code Language Model
Source code에 대한 language model을 만들어 code suggestion, readability improvement, API migration 등의 태스크에 응용하고자 하는 시도는 지속적으로 있었다.
Language model은 어떤 문장이 주어졌을 때 이 문장에 대한 확률을 구하는 모델이다. 이전에 나온 단어 몇 개를 보고 다음에 나올 문장을 예측함으로써 Language Generation Task의 기초가 된다. 이를 코드의 token들에도 동일하게 적용할 수 있게 된다면, code generation과 관련된 유용한 태스크들로 발전시킬 수 있지 않을까? 하지만 이러한 물음에서부터 시작된, NLP2Code와 관련된 여러 연구들에서 공통적으로 맞닥뜨린 문제점은, 코드에서는 공통적이면서 meaningful한 token들이 지속적으로 사용되기보다는 variable identifier 등에 개발자가 임의로, 또는 컨벤션에 의해 새롭게 만들어진 unique word들이 많아서 vocabulary size가 지나치게 커지고 함께 OOV(Out-Of-Vocabulary) 문제도 굉장히 빈번하게 발생한다는 것이다. 이런 문제를 타겟팅하여 소스 코드의 Open-Vocabulary Model을 구성한 논문이 이목을 끌었다.
Big Code ≠ Big Vocabulary: Open Vocabulary Models for Source Code
소스 코드에서의 NLM(Neural Language Model)의 scalability, out-of-vocabulary 문제를 해결하기 위해, 이 논문에서 제시한 주요한 contribution은 Byte Pair Encoding(BPE)을 사용하여 open vocabulary source code NLM을 구성한 것이다. 먼저 다양한 vocabulary design이 모델의 OOV rate와 scalability에 어떻게 영향을 미치는지를 조사하고, 기존에 사용되던 n-gram LM과 closed vocabulary NLM을 베이스라인으로 large scale experiment를 진행하였다.
- Vocabulary modeling을 위해서 적용한 테크닉은 크게 Filtering (Only-english, whitespace, comments, string literals), Splitting(convention e.g. camelCase), 그리고 Spiral, Stemming, BPE와 같은 subword splitting이다. Spiral은 기존의 Mining Software Repository 테크닉에서 사용하던 SOTA인데, vocabulary를 26% 정도 줄이고 3% 정도의 괜찮은 OOV rate를 기록했지만, BPE는 frequent한 subsequence들을 캡쳐함으로써 10K개라는 굉장히 작은 vocabulary size를 달성하면서도 OOV 문제가 발생하지 않도록 하며, 거의 모든 단어들이 corpus에서 90% 이상의 frequency를 달성한다.
- 이렇게 BPE로 모델링한 Vocabulary를 가지고 RNN(GRU) 기반 Language Model을 구성한다. single layer GRU NLM을 base model로 설정하고 GRU unroll을 200 time step만큼 수행한다.
- Vocabulary는 subword unit이지만, 실제 prediction의 결과물로 필요한 것은 complete token이다 (마지막 word가 <t>, 즉 공백으로 끝나는). 그러므로 customized beam search를 사용해서 주어진 subword unit의 probability로부터 top k complete tokens를 제공하도록 한다. maximize 하고자 하는 것은 이전에 나온 subword units들에 대한 complete token(sequence of units) 의 conditional probability가 된다.
- Caching mechanism을 함께 구현했다. source code의 locality를 활용하고자 하는 것인데, 기존에 정의된 identifier가 반복되는 경우 일부 (여기서는 5개) token들이 이전에 이미 predict 되었던 것과 동일하면, 추가적인 prediction을 수행할 필요 없이 캐시에 저장된 history를 이용해서 나머지 token들을 채우게 된다. 최종적으로 이렇게 캐시된 것이 바로 사용되는 것이 아니라, top k 결과를 리포트할 때에는 이후 beam search에서 나온 probability와 합쳐져서 사용된다.
- Evaluation은 주어진 토큰들의 cross entropy를 계산하여 prediction confidence를 확인하는 intrinsic, code completion task를 명확히 정의하여 수행한 extrinsic 두 가지 시나리오로 구성되었다. 결과를 간단히만 report하자면, 기존에 closed vocabulary에서 성능이 좋지 않다고 생각되었던 NLM이 BPE와 결합되었을 때에는 nested cache model을 능가하는 성능을 보여주었다. 전반적으로 n-gram language model에 비해서는 long range dependency의 효과로 큰 데이터에 대해서 좋은 성능을 보여주었고, cache model에 비해서는 cache의 기회가 적은 작은 데이터(e.g. Python project)에 대해서 outperform하는 양상을 보였다. 이 외에도 다양한 language, corpora size에 대한 시나리오에서 다양한 소스 코드 LM과의 비교를 제공하여, 다양한 insight를 주는 논문이었다.
Deep Learning Testing & Debugging
ReluDiff: Differential Verification of Deep Neural Networks
-
SE에서의 formal verification technique을 DNN에 적용하고자 하는 시도. 기존의 SOTA verification technique에는 RELUPLEX, RELUVAL, DEEPPOLY 등이 있는데, 이들은 formal proof를 바탕으로 single network에 대한 분석만을 제공한다.
Formal verification: 알고리즘과 시스템의 correctness를 formal specification이나 property에 대해, theorem prover와 같은 formal method를 통해 보이는 것.
- 이 논문에서는 compressed network와 기존 network의 비교 상황에서 특히 유용한, 두 연관된 뉴럴 네트워크 사이의 differential verification 테크닉을 제안한다.
-
기존의 SOTA verification technique들이 “두 개의 동일한(identical) 네트워크가 같다(same)” 라는 것을 보일 수 없었기 때문에 (over-approximation), backward-pass refinement step을 추가하여 subregion에 대한 valication을 iterative하게 수행하게 된다.
-
단순한 symbolic execution을 DNN에 적용하게 되면 ReLU activation을 approximate하면서 resulting output interval이 지나치게 커지게 되지만, 각기 다른 네트워크에 존재하는 neuron간의 관계를 계속 유지하고 이들의 difference를 tracking하면 훨씬 더 fine-grained된 interval을 찾을 수 있다.
-
Input region을 subregion으로 나눈다는 것은 무슨 말일까? 더 작은 범위의 input에 대해서는 ReLU activation의 approximation 오차가 훨씬 적어지기 때문에, ReluDiff에서는 gradient 오차를 계산하여 어떤 input이 output difference에 더 많은 영향을 주었는지를 판단하고, 이 input interval에 대한 subregion split을 수행한다.
-
처음으로 두 네트워크 간의 differential verification을 수행한 논문이기 때문에 기존의 DNN verification tool은 두 네트워크를 합친 새로운 네트워크에서 결과값의 차를 구하도록 바꿔서 evaluation을 수행하였다.
- 기존의 소프트웨어에서 differential verification이라는 용어는 프로그램의 새로운 버전을 이전 버전에 대해 verify할 때 사용되었고, 이전 버전은 oracle로써 사용되었다.
Structure-Invariant Testing for Machine Translation
Neural Machine Translation을 대상으로 이를 테스팅하고자 하는 기법들이 소개되었다. 그 중 하나가 structure-invariant testing으로써, metamorphic testing을 기반으로 비슷한 source sentence들을 translate한 결과가 동일한 structure를 유지해야 한다는 metamorphic relationship을 이용해서 테스트를 생성한다.
그 결과 under-translation, over-translation, incorrect modification, word/phrase mistranslation, unclear logic과 같은 다양한 taxonomy에 있는 translator의 에러를 검출해냈다.
여기서 제안하는 structure-invariant testing(SIT)의 아이디어는 비교적 간단하지만 (source sentence에서 single word modification), BERT와 같은 language model을 적용하여 의미적으로 비슷한 문장들을 생성하고, Constituency parse tree, 또는 dependency parse tree를 이용하여 변환된 문장을 structure 단위에서 similarity를 비교하게 된다.
Automatic Testing and Improvement of Machine Translation
앞의 논문과 비슷하게, 이 논문에서 제시하는 TransRepair는 context-similar word replacement를 통해 다양한 input을 generate하지만, 한 가지 새로운 점은 inconsistency를 detect하여 그러한 output을 자동으로 고치는 것까지 수행한다는 것이다. 즉 여러 비슷한 sentence들을 한꺼번에 번역하고, 그 안에서의 best translation을 탐색하여 보다 정확한 output을 모델이 제공할 수 있도록, NMT model의 robustness를 향상시키는 추가적인 스텝을 제공한다.
Inconsistency repair의 방법으로는 machine의 predictive probability를 직접 확인하여 가장 confidence가 높은 것을 채택하는 grey-box approach, 그리고 결과물로 나온 sentence들만을 직접 비교하여 cross-reference를 확인하는 black-box approach를 소개한다. (Google Translator와 같이 prediction probability를 확인할 수 없는 경우)
Testing DNN Image Classifier for Confusion & Bias Errors
또 다른 DNN Testing은 Image Classifier의 영역에서 소개되었다. misclassification의 이유를 특정 클래스들에 대한 bias로 보고, class property violation을 기반으로 confusion & bias error를 detect하는 프레임워크를 제시한다. 기존에 제시되었던 DNN testing technique과 구분되는 점은, misclassification이 일어난 각 이미지에 집중하는 것이 아니라, class level에서 모델이 어떤 일반적인 bias를 갖고 있는지를 확인한다는 점이다.
잘 알려진 classifier bug들 중에서는 전체 class의 영역에서 종합적으로 발생한 것들이 많다. 2015년에 이슈가 된 Gorilla Tag (흑인들의 사진이 Google Photo 앱에서 고릴라로 태깅된 사건), Google Photo에서의 skier과 mountain에 대한 혼동, Gender Shades (오픈소스 얼굴인식 서비스가 유색인종 여성들에 대해 높은 에러율을 보임) 등이 그 예시다. 이러한 버그들을 크게 Confusion (두 클래스를 구별하지 못하는 것) / Bias (연관된 그룹(e.g. genders)에 대해 다른 결과를 내놓는 것) 로 나누어 설명한다.
이러한 Class-level violation을 감지하기 위해서 Pretrained model에 대해 neuron-coverage metric을 사용한다. 각 class에 해당하는 input들이 일정 threshold 이상 활성화시킨 뉴런들을 vector로 이어 붙이게 되면, Neural-Path per Class를 얻을 수 있고, 어떤 뉴런이 어떤 클래스에 의해 활성화될 확률을 conditional probability로 추산한 확률을 Matrix로 만들 수 있다. (Neuron Activation Probability)
- Confusion Error Detection: 두 클래스 사이의 confusion score를 neuron activation vector들의 euclidean distance로 계산하여, 구별하기 힘든 class들을 찾아내게 된다.
- Bias Error Detection: 여기에서는 세 개의 클래스 사이의 관계를 이용하여, 특정 class c에 대해서 class a와 b 사이의 bias가 있는지를 확인한다. a와 b를 제외한 모든 클래스 Object들에 대해서 계산한 bias를 average한 값을 사용하여, 일정 threshold를 넘으면 bias가 있다고 판별한다. (왜 average를 하는 거지, 특정 class c에 대해서 큰 bias를 보이면 그걸로 bias 있는지 확인되는 게 아닌가)
- Ground Truth를 설정하는 과정이 흥미로운데, test set에 존재하는 misclassified image들에 대해 probability of misclassification between class A and B를 구하고 그럴 확률이 1 std보다 높은 것들을 ‘confusion error’가 일어났다고 보고 ground truth로 설정한다. 이는 class-level로 에러를 detect함으로써 생기는 inherent probabilistic nature 때문이다.
Repairing Deep Neural Networks: Fix Patterns and Challenges
Caffe, Keras, Tensorflow, Theano, Torch와 같은 다양한 DNN Framework를 사용한 Stack Overflow code snippet들과 github project에 대한 bug dataset을 구성했다. 또한 이렇게 마이닝된 버그들의 fix pattern을 함께 분석하여 새로운 bug classification을 제안했는데, Data dimension, Network Connection, Data type, Layer dimension, Loss function 등과 같은 fix pattern 각각에 대한 distribution도 함께 제공한다.
가장 많은 수의 fix들이 data dimension에 관한 것들이었는데, 이중 resize는 information 손실로 인한 성능 감소를 일으키는 경우가 많았고, reorder과 reshaping은 DNN specification과 library에 대한 이해를 기반으로 이루어져야 한다는 finding을 제시한다. 이외에도 layer dimension fixes는 crash-related bug와 연관되어 있고, library-version related fixes, network connection bug로 인한 crash, incorrect functionality, bad performance와 같은 현상을 확인한다.
추가적으로 29%의 bug fixes들이 사실은 새로운 bug들을 introduce한다는 사실도 흥미로웠다.
전체적으로, DNN 시스템에서 발견되는 버그에 대한 empirical study는 많았지만 이 연구에서는 특히 개발자들이 실제 버그를 고치는 ‘과정’에 대한 좀더 qualitative한 분석과, 이러한 fix들을 automate하는 데에 어떤 challenge가 있을지 좀더 명확하게 identify하고자 노력한 것 같다. DNN의 API bug에 대한 좀더 깊은 이해를 바탕으로 data dimension과 layer spec간의 mismatch를 해결하고, DNN model을 어떻게 더 reusable하게 만들 수 있는지에 대한 further research direction에 대해 탐구해 볼 여지가 있는 것 같다. arxiv link
Program Analysis and Verification
On the Recall of Static Call Graph Construction in Practice
Static analysis를 통해서 dynamic language feature를 정확하게 모델링하는 것은 어렵다. 하지만 이 imprecision이 실제로 real-world program에 어느 정도의 영향을 미치는지에 대해서 확인된 바가 없기 때문에, 여기에서는 31개의 real-world Java program을 대상으로 실제 program behavior와 다양한 static anaylysis algorithm + configuration으로 모델링한 결과를 비교한다.
논문의 evaluation methodology를 간단히 살펴보면 static call graph(SCG)와 실제 execution을 통해 만들어진 CCT(Context Call Tree)를 oracle로 사용하여 sound (no false negatives) 한지 / precise (no false positives) 한지를 확인하는 것이다. CCT의 impractical한 점은 바로 size에 있는데, loop로 인해 만들어진 redundant branch를 제거하는 과정을 통해서 reachability 정보를 망가뜨리지 않으면서도 성공적으로 그래프 사이즈를 줄일 수 있었다고 한다.
추가적으로 reachable하지 않은 SCG의 노드들에 대해서 cause도 함께 파악했는데, Dynamic Invocations (DI), Dynamic Allocations (DALL) 등과 같은 경우들이 존재했다. CCT를 만들 때에는 기존에 존재했던 built-in test 외에도 branch coverage를 높이기 위해 Evosuite과 같은 test generation framework로 만들어진 테스트들을 추가적으로 활용했는데, built-in test로 만들어진 call context를 oracle로 할 때의 recall이 generated test보다 현저히 낮았다. 즉, built-in test가 프로그램의 가능한 behavior를 더 풍부하게 설명한다는 것이다. state-of-the-art dynamic language feature support를 통해서 recall을 0.884에서 0.935까지 올릴 수 있었지만 성능에는 크게 부정적인 영향을 미쳤고, unsoundness의 주요한 이유는 not reflective method invocation, JVM에서부터 발생한 invocation, native method로부터 접근한 object들이 있었다.
mCoq: Mutation Analysis for Coq Verification Projects
Coq에 대해서 이 논문에서 처음 알게 되었는데, Coq는 Programming Language의 관점에서 dependently typed functional programming language로 볼 수 있고, CompCert C compiler와 같은 프로그램들이 Coq에 의해 correctness verification이 이루어졌다고 한다. 여기서 소개하는 MCoq이라는 툴은 기존의 Java와 같은 프로그래밍 언어가 아니라 Coq project를 대상으로 mutation analysis를 제공한다. 소스 파일에 여러 mutation operator를 적용하는 것은 동일하지만, specification property (혹은 proof)가 test의 역할을 하게 된다. Paper Link
Bugs and Repair
FixMiner: Mining Relevant Fix Patterns for Automated Program Repair
FixMiner는 ESE에 소개된 Journal 논문인데, mining한 패치에서 reusable한 fix pattern을 찾아냄으로써 (iterative clustering strategy에 기반한) 81%의 correctness probability를 달성한 patch generation 테크닉이다. 여기서 Rich Edit Script라는 컨셉을 제안하는데, code change의 AST-level context를 성공적으로 임베딩하는 특별한 트리 데이터 구조이고, 각각 ShapeTree, ActionTree, TokenTree 의 세 가지 컨텍스트를 분리하여 저장한다. 이를 통해 좀더 fine-grained level에서 패치 간 similarity를 확인할 수 있다. arxiv
DLFix: Context-based Code Transformation Learning for Automated Program Repair
또다른 APR 논문인데, 여기서의 특이한 점은 two-tier DL model, 즉 fix에 사용되는 주변 context를 embedding하는 레이어와 실제 fix되는 부분을 분리하여 transformation하는 레이어, 두 가지 스텝으로 patch generation을 구성했다는 점이다. surrounding code context가 fix에 중요한 역할을 한다는 점을 고려했을 때, 먼저 주변 컨텍스트에서 중요한 부분을 배우고, 실제로 버그가 일어난 statement를 특정하여 패치를 생성한다는 것이 single-line bug에 대해서 좋은 성능을 보인 이유라고 생각되었다.