今天,基于神經(jīng)網(wǎng)絡(luò)的人工智能正處于一個非常有趣的發(fā)展階段。它顯然已經(jīng)起飛:我們看到從讀取CT掃描到采摘水果的許多應(yīng)用。但采用率差異很大。推薦引擎、客戶支持機器人和其他被稱為“互聯(lián)網(wǎng) AI”的東西相當(dāng)普遍;我們在生活中隨處可見它。然而,大多數(shù)領(lǐng)域,包括軟件測試,還沒有完全實現(xiàn)。
是什么讓人工智能被廣泛采用,是什么讓它陷入困境?讓我們來看看我們自己的領(lǐng)域,軟件測試。具體來說,我想看看神經(jīng)網(wǎng)絡(luò)如何生成自動化測試,以及在我們的領(lǐng)域大規(guī)模采用人工智能存在哪些障礙。我將首先關(guān)注問題和困難,不是因為我試圖成為半空的玻璃杯,而是因為出錯的事情總是告訴我們更多關(guān)于系統(tǒng)如何運作的信息,而不是正確的事情。
一旦我們完成了生成測試,我想看看人工智能在其他領(lǐng)域的應(yīng)用,比如醫(yī)學(xué)——那里有很多工作要做,尤其是閱讀掃描。也許他們有類似的成長痛苦?最后,為了鳥瞰,我將看看一個完全不同的行業(yè),它已經(jīng)成熟和鞏固。它的經(jīng)驗?zāi)芨嬖V我們今天人工智能的發(fā)展嗎?
有了這個角度,也許我們可以停止困擾新技術(shù)的炒作/幻滅鐘擺,也許可以瞥見人工智能的發(fā)展方向。
確認(rèn)
在我們繼續(xù)之前,我要感謝納塔利婭·波利亞科娃和阿爾喬姆·埃羅申科為我提供了這篇文章的時間和專業(yè)知識。但是,所寫一切的責(zé)任完全在于我。
另外,非常感謝Danil Churakov在此(和其他)帖子中提供的精彩圖片!
生成測試:現(xiàn)在的位置
今天,ChatGPT,GitHub Copilot和其他AI驅(qū)動的工具被廣泛用于編寫代碼和測試,我們最近對此進(jìn)行了一次非常有趣的采訪。然而,人們?nèi)匀淮蠖嗍鞘止ぞ帉懽詣踊瘻y試,神經(jīng)網(wǎng)絡(luò)的使用主要是情境化的。他們在這一領(lǐng)域達(dá)到目標(biāo)的速度仍然遠(yuǎn)低于人類的標(biāo)準(zhǔn)。 2020 年末的一篇論文預(yù)測了測試中 62% 的斷言陳述,這絕對是一個值得吹噓的結(jié)果。根據(jù)GitHub Copilot的常見問題解答,它的建議在26%的時間內(nèi)被接受。人們常說,它最好的用途是作為谷歌和StackOverflow的更快替代品。所以 - 情境用法。目前,軟件QA中的AI還不能與營銷等領(lǐng)域擁有相同的水平,在市場營銷中,神經(jīng)網(wǎng)絡(luò)創(chuàng)建的數(shù)字營銷和數(shù)據(jù)分析策略實際上優(yōu)于人類創(chuàng)建的數(shù)字營銷和數(shù)據(jù)分析策略。但是,請記住,GPT-4 可能會改變情況。
這些問題從何而來?讓我們四處打聽并做一些實際研究。我和我經(jīng)驗豐富的測試人員同事談過,也修改了Machinet,這是一個非常流行的IDEA插件,可以生成單元測試。
我們使用的神經(jīng)網(wǎng)絡(luò)對于其預(yù)期應(yīng)用非常有用。Machinet可能是作為開發(fā)人員助手而不是通用工具創(chuàng)建的。他們的座右銘聽起來絕對像是針對開發(fā)人員而不是QA:“讓我們面對現(xiàn)實吧。單元測試是一件苦差事。只需自動化即可。這是有道理的——通常是開發(fā)人員編寫單元測試。對于沒有深入了解測試的人來說,該工具做得很好。只有當(dāng)我們從 QA 的角度來看待結(jié)果時,故障才會變得可見。那么存在哪些問題呢?
A. 問題
工作中的網(wǎng)絡(luò)
過度承保
Machinet 插件完成了它的工作,并且做得很徹底 - 它確保覆蓋 if-else 分支、使用不同的數(shù)據(jù)類型、檢查字符限制等。事實上,它完成的工作太徹底了,可以生成太多的測試,而不考慮資源負(fù)載。例如,檢查字段是否接受任何字符并檢查它是否將字符串長度限制為 255 個字符可以在單個測試中輕松完成 - 但 Machinet 為每種情況生成了一個單獨的測試。另一個示例涉及由多個 API 方法使用的數(shù)據(jù)檢索功能。生成的測試將涵蓋每個方法中的函數(shù),并且將為函數(shù)本身創(chuàng)建一個單獨的測試。同樣,我們顯然得到了過度的報道。
印象是,如果我們有幾個相交的數(shù)據(jù)集,插件將嘗試覆蓋所有可能的交集。假設(shè)您正在測試一個電子商務(wù)網(wǎng)站,并且您有多種交付選項(客戶取貨、付款類型等)。使用Machinet,所有可能的組合都可能會被測試,而人類測試人員可以使用決策表來涵蓋真正重要的組合。但是,這樣做可能需要未輸入神經(jīng)網(wǎng)絡(luò)的上下文數(shù)據(jù)。
代碼重復(fù)
一個相關(guān)的問題是代碼重復(fù)。我們正在測試一個需要填充對象的集合,它必須在 4 個不同的測試中使用。每個測試都從頭開始重新創(chuàng)建集合,而不是將其移動到單獨的字段或函數(shù)中。此外,代碼中已經(jīng)存在一個用于生成集合的函數(shù),它執(zhí)行的操作與測試中所做的基本相同,但插件沒有使用它。神經(jīng)網(wǎng)絡(luò)能很好地使用本地的東西?很容易說,嗯,這是網(wǎng)絡(luò)以前從未遇到過的獨特情況。但這并不像神經(jīng)網(wǎng)絡(luò)在識別它以前見過的獨特貓照片時會遇到任何困難。這是一個有趣的問題,我們將在下面回到。
了解復(fù)雜代碼
神經(jīng)網(wǎng)絡(luò)生成的自動化測試在涵蓋簡單的模塊化代碼片段時處于最佳狀態(tài)。當(dāng)然,如果所有代碼都以這種方式編寫,那就太好了,但這可能是不可能的或不可行的。當(dāng)您需要涵蓋冗長而復(fù)雜的業(yè)務(wù)邏輯時,機器生成的測試的可靠性會受到很大影響。當(dāng)然,它們會被生成,但很難弄清楚它們是否正確地覆蓋了東西,或者它是否只是隨機的東西,幾乎不能指望用于煙霧測試。
了解上下文
在談到過度覆蓋時,我已經(jīng)談到了這一點:網(wǎng)絡(luò)并不真正知道該方法的用途,因此無法根據(jù)這些知識進(jìn)行優(yōu)化。例如,人類測試人員知道,如果我們在 Java 中測試 API 方法,我們應(yīng)該檢查空值;如果不是 API,則可以跳過此操作。我們看到的網(wǎng)絡(luò)似乎不會做出這樣的決定。
外部工具和模式的使用
我們還注意到,Machinet 使用硬編碼值填充集合,而不是使用庫隨機生成數(shù)據(jù)。我不知道這是否是一個過分的要求,但有一個相關(guān)的問題:我們使用的神經(jīng)網(wǎng)絡(luò)在外部依賴關(guān)系方面做得不好,使用模式也是一個問題。
清理
最后,網(wǎng)絡(luò)生成的代碼肯定需要徹底審查。當(dāng)然,所有由人類編寫的代碼也需要審查,這是標(biāo)準(zhǔn)做法,基于AI的工具的創(chuàng)建者總是警告這一點。在開發(fā)此類工具時,絕對必須牢記這一點:會有很多來回,使編輯變得容易應(yīng)該是首要考慮因素。但這可能是一個問題還有另一個原因。正如我所說,Machinet 似乎針對那些可能不太熟悉測試的開發(fā)人員;因此,審查機器工作的人可能無法糾正我剛才談到的所有缺陷。
問題背后的原因
因此,當(dāng)需要深入了解本地項目時,我們一直在使用的工具并不那么好,不“理解”他們正在測試的方法的上下文,他們不擅長在重復(fù)或資源使用方面優(yōu)化代碼,他們最擅長簡單和模塊化的代碼,他們創(chuàng)建的代碼也往往是這樣。
乍一看,這些似乎是相當(dāng)深層次的問題,但也許這是因為我們在談?wù)摗袄斫狻倍皇窃谡務(wù)摂?shù)據(jù)。毫不奇怪,如果沒有對 RAM 和 CPU 使用率的數(shù)據(jù)進(jìn)行訓(xùn)練,網(wǎng)絡(luò)就無法根據(jù)資源消耗優(yōu)化代碼。ChatGPT 不了解您的特定項目,因為它沒有接受過培訓(xùn)。最后,這些障礙不是代碼固有的,這只是一個經(jīng)濟(jì)學(xué)問題:在特定數(shù)據(jù)集上訓(xùn)練網(wǎng)絡(luò)是否可行。
更深層次的原因本身就是代碼嗎?
然而,這里有一個更深層次的問題:代碼與人類語言不同。這個問題已經(jīng)得到了很好的研究,并且已經(jīng)為自然語言開發(fā)的算法絆倒了一段時間。如果我們將自然語言與您主要“按原樣”使用的工具進(jìn)行比較,那么編程語言就是您用來構(gòu)建工具的工具,以構(gòu)建工具來構(gòu)建工具。它更加嵌套。
對XKCD最好的問候
程序員編寫的每個新函數(shù)或變量都有自己的名稱,這些名稱可能會變得非常長且難以理解 - 特別是Java因VariableNamesThatLookAndFeelLikeTrainWrecks而臭名昭著。
這意味著,例如,Ubuntu 的源代碼可以比大量的英語文本語料庫多兩個數(shù)量級的獨特“單詞”(嗯,標(biāo)記)。這是一個非常大且非常稀疏的詞匯;對于任何算法來說,這兩者都是壞消息。生僻詞意味著要學(xué)習(xí)的數(shù)據(jù)較少,詞匯量會影響算法的速度和內(nèi)存要求。
這些嵌套詞匯表也非常本地化。您在項目中使用的大多數(shù)單詞永遠(yuǎn)不會看到外部。這就是封裝的重點:突出的東西越少,代碼就越容易使用。因此,您擁有特定于應(yīng)用程序甚至開發(fā)人員的詞匯表。此外,人們使用的工具也在不斷變化,這也催生了新的詞匯。除此之外,還有風(fēng)格:我們編寫的代碼可能非常固執(zhí)己見。那是你剛剛寫的Pythonic嗎?還是你還在拖著你舊的Java習(xí)慣?同樣的問題可以用不同的方式解決,造成進(jìn)一步的混亂。
因此,想象一下您的技術(shù)堆棧。你有你的語言(也許是幾種語言),你的框架,你的數(shù)據(jù)庫,你在前端和后端擁有的所有庫,以及你使用的模式,以及開發(fā)人員的特質(zhì)。所有這些交叉上下文都嚴(yán)重限制了任何特定AI驅(qū)動工具的類似代碼的數(shù)量。因此,難怪這些工具在生成復(fù)雜代碼時會遇到麻煩。
問題很深,但還不夠深
當(dāng)然,這是一個問題,但遠(yuǎn)非不可克服。問題是,在由語言、框架、項目等定義的上下文中,代碼實際上比人類語言重復(fù)得多(另請參閱此處)。而那個重復(fù)的部分是占主導(dǎo)地位的部分。一項研究發(fā)現(xiàn),大量 JavaScript 文件包含 2 萬個唯一標(biāo)識符,但其中只有 4k 個負(fù)責(zé)所有事件中的 10%。
因此,這不是數(shù)據(jù)(我們的代碼)的深層問題,而是數(shù)據(jù)如何組織以及如何將其輸入工具的問題。也許可以通過使用一種訓(xùn)練子詞而不是單詞的算法來解決。這樣的算法不必處理數(shù)百萬字長的詞匯表,但它會更耗費資源。或者,也許是關(guān)于擁有一個可以足夠快地重新估計的模型,以便它可以適應(yīng)您的本地環(huán)境。或者,也許我們應(yīng)該將上下文信息(如注釋)提供給算法。無論如何,答案始終是關(guān)于我們?nèi)绾谓M織數(shù)據(jù)以及處理數(shù)據(jù)的速度。
饋送網(wǎng)絡(luò)
縮小:人工智能的演變
讓我們試著把這些問題放在正確的角度,看看它們與人工智能在其他領(lǐng)域必須克服的困難相比如何。
無論如何,神經(jīng)網(wǎng)絡(luò)的歷史圍繞著在更短的時間內(nèi)處理更多的數(shù)據(jù)。這是我一開始不太明白的:對于神經(jīng)網(wǎng)絡(luò),數(shù)量就是質(zhì)量;數(shù)據(jù)越多,答案就越復(fù)雜和準(zhǔn)確。
幾乎只要有計算機,人們就一直在嘗試構(gòu)建神經(jīng)網(wǎng)絡(luò),但在大部分時間里,人工智能被不同的學(xué)校主導(dǎo),即“基于規(guī)則”的方法:告訴你的系統(tǒng)規(guī)則并觀察它的工作;如果失敗 - 請咨詢專家,制定新規(guī)則。相比之下,神經(jīng)網(wǎng)絡(luò)根據(jù)它們處理的數(shù)據(jù)自己找出規(guī)則。那么,為什么網(wǎng)絡(luò)只是在過去一二十年才“起飛”呢?因為那時我們獲得了大規(guī)模的數(shù)據(jù)存儲(特別是云)、瘋狂的大量生成數(shù)據(jù)(通過物聯(lián)網(wǎng)等)和巨大的處理能力(尤其是 GPU 計算);就在那時,發(fā)生了幾項創(chuàng)新,大大提高了深度神經(jīng)網(wǎng)絡(luò)的訓(xùn)練效率,從 2000 年代中期的 Geoffrey Hinton 的工作到 2018 年變壓器的發(fā)明。長話短說,可以快速處理大量數(shù)據(jù)。
但僅僅擁有算法和硬件可能還不夠。醫(yī)療保健是一個收集和存儲大量數(shù)據(jù)的領(lǐng)域,一直在尋找尖端技術(shù),并吸引大量投資。因此,在某些地方和某些領(lǐng)域(如眼科),人工智能已經(jīng)進(jìn)入日常使用也就不足為奇了。然而,在廣泛采用之前還有很長的路要走。在醫(yī)療保健領(lǐng)域,與編程不同,確實存在優(yōu)于人類的模型,但它們大多停留在開發(fā)階段,并且在實施中不斷失敗。
原因是,與用于訓(xùn)練模型的集合相比,現(xiàn)實生活中的數(shù)據(jù)是“臟的”。目前,醫(yī)院的數(shù)據(jù)都以不同的方式收集和存儲,醫(yī)院通常有幾個系統(tǒng),除了通過pdf文件外,它們不會相互通信。當(dāng)然,數(shù)據(jù)基礎(chǔ)設(shè)施因醫(yī)院而異,因此您無法構(gòu)建任何大規(guī)模數(shù)據(jù)集。此外,患者可能與用于訓(xùn)練模型的人口統(tǒng)計數(shù)據(jù)不同。此外,從業(yè)者使用的一些信號沒有數(shù)字化,這降低了模型的比較效率。在本地數(shù)據(jù)集上訓(xùn)練模型時,存在患者保密問題。
進(jìn)入狹窄的空間
一般來說,有兩種方法可以繞過這些障礙:使模型適合現(xiàn)實生活中的使用給我們帶來的狹窄空間,或者擴(kuò)大空間。
用于訓(xùn)練醫(yī)療保健中表現(xiàn)最佳的模型的大型數(shù)據(jù)集是通過由于專有原因無法在現(xiàn)實生活中重現(xiàn)的步驟創(chuàng)建的。因此,可以在局部環(huán)境中校準(zhǔn)模型以提高其準(zhǔn)確性,而合成數(shù)據(jù)集可用于保護(hù)機密性。
但是,如果不改變用于收集和存儲數(shù)據(jù)的基礎(chǔ)設(shè)施,所有這些都不可能非常有效。現(xiàn)有的系統(tǒng)必須能夠相互連接,數(shù)據(jù)應(yīng)該像STRIDES倡議所提議的那樣存儲在異地,最重要的是,它必須變得更加統(tǒng)一。
不出所料,代碼和醫(yī)療保健中采用問題背后的原因非常不同。解決方案則不然。我們可以預(yù)期這些模型在重新訓(xùn)練以適應(yīng)當(dāng)?shù)丨h(huán)境方面會變得更便宜、更有效。我們可以改變組織數(shù)據(jù)的方式。為了使網(wǎng)絡(luò)更高效地處理代碼和測試,我們需要更標(biāo)準(zhǔn)化的編寫和存儲方式。我們認(rèn)為的“干凈代碼”的許多實踐旨在使代碼對人類更具可讀性。也許我們現(xiàn)在需要的是使其對神經(jīng)網(wǎng)絡(luò)更具可讀性的方法。
或者也許它更簡單。如果神經(jīng)網(wǎng)絡(luò)可以生成簡單、重復(fù)的代碼,并且善于用測試來覆蓋它——那么也許我們讓它們做工作的兩面,完全忘記干凈的編碼實踐,而是專注于控制輸出的方法。
總結(jié)
當(dāng)一項新技術(shù)出現(xiàn)時,有兩種采用途徑:首先,該技術(shù)試圖適應(yīng)經(jīng)濟(jì)中已經(jīng)存在的一些角色;然后,經(jīng)濟(jì)發(fā)生變化,以適應(yīng)新技術(shù)的全面發(fā)展。第二條路徑意味著創(chuàng)建一個基礎(chǔ)設(shè)施網(wǎng)絡(luò)來支持該技術(shù)。如果你有汽車,你也會得到新道路的大規(guī)模建設(shè),你會得到立法的變化,等等。如果你想要電動汽車,你需要充電器。
這是目前在QA中AI之前的兩條道路,可以幫助將技術(shù)與支持它所需的基礎(chǔ)設(shè)施相結(jié)合:
1. 制作能夠更好地適應(yīng)當(dāng)?shù)丨h(huán)境的人工智能驅(qū)動工具,能夠在特定項目和技術(shù)堆棧上學(xué)習(xí)的工具
2. 使測試的組織方式適應(yīng)神經(jīng)網(wǎng)絡(luò)的要求
審核編輯:郭婷
評論
查看更多