數(shù)據(jù)預(yù)處理是準(zhǔn)備原始數(shù)據(jù)并使其適合機(jī)器學(xué)習(xí)模型的過程。這是創(chuàng)建機(jī)器學(xué)習(xí)模型的第一步也是關(guān)鍵的一步。
創(chuàng)建機(jī)器學(xué)習(xí)項(xiàng)目時(shí),我們并不總是遇到干凈且格式化的數(shù)據(jù)。在對(duì)數(shù)據(jù)進(jìn)行任何操作時(shí),必須對(duì)其進(jìn)行清理并以格式化的方式進(jìn)行存儲(chǔ)。為此,我們使用數(shù)據(jù)預(yù)處理任務(wù)。
為什么我們需要數(shù)據(jù)預(yù)處理?
現(xiàn)實(shí)世界的數(shù)據(jù)通常包含噪聲、缺失值,并且可能采用無法直接用于機(jī)器學(xué)習(xí)模型的不可用格式。數(shù)據(jù)預(yù)處理是清理數(shù)據(jù)并使其適合機(jī)器學(xué)習(xí)模型所需的任務(wù),這也提高了機(jī)器學(xué)習(xí)模型的準(zhǔn)確性和效率。
它涉及以下步驟:
獲取數(shù)據(jù)集
導(dǎo)入庫
導(dǎo)入數(shù)據(jù)集
查找丟失的數(shù)據(jù)
編碼分類數(shù)據(jù)
將數(shù)據(jù)集拆分為訓(xùn)練集和測(cè)試集
特征縮放
1)獲取數(shù)據(jù)集
要?jiǎng)?chuàng)建機(jī)器學(xué)習(xí)模型,我們首先需要的是數(shù)據(jù)集,因?yàn)闄C(jī)器學(xué)習(xí)模型完全依賴于數(shù)據(jù)。以適當(dāng)?shù)母袷结槍?duì)特定問題收集的數(shù)據(jù)稱為數(shù)據(jù)集。
出于不同的目的,數(shù)據(jù)集可能具有不同的格式,例如,如果我們想要?jiǎng)?chuàng)建用于商業(yè)目的的機(jī)器學(xué)習(xí)模型,那么數(shù)據(jù)集將與肝臟患者所需的數(shù)據(jù)集不同。因此每個(gè)數(shù)據(jù)集都不同于另一個(gè)數(shù)據(jù)集。為了在代碼中使用數(shù)據(jù)集,我們通常將其放入 CSV文件中。然而,有時(shí),我們可能還需要使用 HTML 或 xlsx 文件。
什么是 CSV 文件?
CSV 代表“逗號(hào)分隔值”文件;它是一種文件格式,允許我們保存表格數(shù)據(jù),例如電子表格。它對(duì)于巨大的數(shù)據(jù)集很有用,并且可以在程序中使用這些數(shù)據(jù)集。
這里我們將使用一個(gè)演示數(shù)據(jù)集進(jìn)行數(shù)據(jù)預(yù)處理,為了練習(xí),可以從這里下載,“https://www.superdatascience.com/pages/machine-learning。對(duì)于實(shí)際問題,我們可以在線下載數(shù)據(jù)集來自各種來源,例如https://www.kaggle.com/uciml/datasets、https://archive.ics.uci.edu/ml/index.php等。
我們還可以通過使用 Python 的各種 API 收集數(shù)據(jù)來創(chuàng)建數(shù)據(jù)集,并將該數(shù)據(jù)放入 .csv 文件中。
2) 導(dǎo)入庫
為了使用Python進(jìn)行數(shù)據(jù)預(yù)處理,我們需要導(dǎo)入一些預(yù)定義的Python庫。這些庫用于執(zhí)行一些特定的工作。我們將使用三個(gè)特定的庫來進(jìn)行數(shù)據(jù)預(yù)處理,它們是:
Numpy:Numpy Python 庫用于在代碼中包含任何類型的數(shù)學(xué)運(yùn)算。它是Python中科學(xué)計(jì)算的基礎(chǔ)包。它還支持添加大型多維數(shù)組和矩陣。因此,在 Python 中,我們可以將其導(dǎo)入為:
將 numpy 導(dǎo)入為 nm
這里我們使用了nm,它是 Numpy 的簡稱,它將在整個(gè)程序中使用。
Matplotlib:第二個(gè)庫是matplotlib,它是一個(gè) Python 2D 繪圖庫,使用這個(gè)庫,我們需要導(dǎo)入一個(gè)子庫pyplot。該庫用于在 Python 中為代碼繪制任何類型的圖表。它將按如下方式導(dǎo)入:
將 matplotlib.pyplot 導(dǎo)入為 mpt
這里我們使用 mpt 作為該庫的簡稱。
Pandas:最后一個(gè)庫是 Pandas 庫,它是最著名的 Python 庫之一,用于導(dǎo)入和管理數(shù)據(jù)集。它是一個(gè)開源數(shù)據(jù)操作和分析庫。它將按如下方式導(dǎo)入:
在這里,我們使用 pd 作為該庫的簡稱??紤]下圖:
3)導(dǎo)入數(shù)據(jù)集
現(xiàn)在我們需要導(dǎo)入為機(jī)器學(xué)習(xí)項(xiàng)目收集的數(shù)據(jù)集。但在導(dǎo)入數(shù)據(jù)集之前,我們需要將當(dāng)前目錄設(shè)置為工作目錄。要在Spyder IDE中設(shè)置工作目錄,我們需要按照以下步驟操作:
將 Python 文件保存在包含數(shù)據(jù)集的目錄中。
轉(zhuǎn)到 Spyder IDE 中的文件資源管理器選項(xiàng),然后選擇所需的目錄。
單擊 F5 按鈕或運(yùn)行選項(xiàng)來執(zhí)行該文件。
注意:我們可以將任何目錄設(shè)置為工作目錄,但它必須包含所需的數(shù)據(jù)集。
在下圖中,我們可以看到 Python 文件以及所需的數(shù)據(jù)集?,F(xiàn)在,當(dāng)前文件夾被設(shè)置為工作目錄。
read_csv() 函數(shù):
現(xiàn)在要導(dǎo)入數(shù)據(jù)集,我們將使用pandas庫的read_csv()函數(shù),用于讀取數(shù)據(jù)集文件并對(duì)其執(zhí)行各種操作。使用此函數(shù),我們可以在本地以及通過 URL 讀取 csv 文件。
我們可以使用 read_csv 函數(shù),如下所示:
data_set = pd .read_csv('數(shù)據(jù)集.csv')
這里,data_set是存儲(chǔ)數(shù)據(jù)集的變量名稱,在函數(shù)內(nèi)部,我們傳遞了數(shù)據(jù)集的名稱。一旦我們執(zhí)行了上面這行代碼,它將成功地將數(shù)據(jù)集導(dǎo)入到我們的代碼中。我們還可以通過單擊變量資源管理器部分來檢查導(dǎo)入的數(shù)據(jù)集,然后雙擊data_set??紤]下圖:
如上圖,索引從0開始,這是Python中默認(rèn)的索引。我們還可以通過單擊格式選項(xiàng)來更改數(shù)據(jù)集的格式。
提取因變量和自變量:
在機(jī)器學(xué)習(xí)中,區(qū)分?jǐn)?shù)據(jù)集中的特征矩陣(自變量)和因變量非常重要。在我們的數(shù)據(jù)集中,有 3 個(gè)自變量,即Country、Age和Salary,以及一個(gè)因變量Purchasing。
提取自變量:
為了提取自變量,我們將使用Pandas 庫的iloc[ ]方法。它用于從數(shù)據(jù)集中提取所需的行和列。
x = data_set .iloc[:,:-1].values
在上面的代碼中,第一個(gè)冒號(hào)(:)用于獲取所有行,第二個(gè)冒號(hào)(:)用于獲取所有列。這里我們使用了 :-1,因?yàn)槲覀儾幌氩捎米詈笠涣?,因?yàn)樗蜃兞?。通過這樣做,我們將得到特征矩陣。
通過執(zhí)行上面的代碼,我們將得到如下輸出:
[['India' 38.0 68000.0] ['France' 43.0 45000.0] ['Germany' 30.0 54000.0] ['France' 48.0 65000.0] ['Germany' 40.0 nan] ['India' 35.0 58000.0] ['Germany' nan 53000.0] ['France' 49.0 79000.0] ['India' 50.0 88000.0] ['France' 37.0 77000.0]]
正如我們?cè)谏厦娴妮敵鲋锌吹降?,只有三個(gè)變量。
提取因變量:
為了提取因變量,我們將再次使用 Pandas .iloc[] 方法。
y = data_set .iloc[:,3].values
在這里,我們僅獲取了所有行和最后一列。它將給出因變量的數(shù)組。
通過執(zhí)行上面的代碼,我們將得到如下輸出:
輸出:
array(['No', 'Yes', 'No', 'No', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes'], dtype=object)
數(shù)據(jù)類型=對(duì)象)
注意:如果您使用Python語言進(jìn)行機(jī)器學(xué)習(xí),則提取是必需的,但對(duì)于R語言則不需要。
4)處理缺失數(shù)據(jù):
數(shù)據(jù)預(yù)處理的下一步是處理數(shù)據(jù)集中缺失的數(shù)據(jù)。如果我們的數(shù)據(jù)集包含一些缺失的數(shù)據(jù),那么它可能會(huì)給我們的機(jī)器學(xué)習(xí)模型帶來巨大的問題。因此,有必要處理數(shù)據(jù)集中存在的缺失值。
處理缺失數(shù)據(jù)的方法:
處理缺失數(shù)據(jù)主要有兩種方法:
通過刪除特定行:第一種方式通常用于處理空值。這樣,我們只需刪除由空值組成的特定行或列即可。但這種方式效率不高,刪除數(shù)據(jù)可能會(huì)導(dǎo)致信息丟失,從而無法給出準(zhǔn)確的輸出。
通過計(jì)算平均值:這樣,我們將計(jì)算包含任何缺失值的該列或行的平均值,并將其放在缺失值的位置。該策略對(duì)于具有年齡、薪水、年份等數(shù)字?jǐn)?shù)據(jù)的特征非常有用。在這里,我們將使用這種方法。
為了處理缺失值,我們將在代碼中使用Scikit-learn庫,其中包含用于構(gòu)建機(jī)器學(xué)習(xí)模型的各種庫。這里我們將使用sklearn.preprocessing庫的Imputer類。下面是它的代碼:
#處理缺失數(shù)據(jù)(用平均值替換缺失數(shù)據(jù)) 從 sklearn.preprocessing 導(dǎo)入 Imputer imputer = Imputer (missing_values = 'NaN' , 策略= '平均值' , 軸 = 0 ) #將imputer對(duì)象擬合到自變量x。 imputer imputer = imputer.fit(x[:, 1:3]) #用計(jì)算出的平均值替換缺失數(shù)據(jù) x[:, 1:3]= imputer.transform(x[:, 1:3])
輸出:
array([['India', 38.0, 68000.0], ['France', 43.0, 45000.0], ['Germany', 30.0, 54000.0], ['France', 48.0, 65000.0], ['Germany', 40.0, 65222.22222222222], ['India', 35.0, 58000.0], ['Germany', 41.111111111111114, 53000.0], ['France', 49.0, 79000.0], ['India', 50.0, 88000.0], ['France', 37.0, 77000.0]], dtype=object
正如我們?cè)谏厦娴妮敵鲋锌吹降?,缺失值已被替換為其余列值的平均值。
5)編碼分類數(shù)據(jù):
分類數(shù)據(jù)是具有某些類別的數(shù)據(jù),例如在我們的數(shù)據(jù)集中;有兩個(gè)分類變量,Country和Purchasing。
由于機(jī)器學(xué)習(xí)模型完全適用于數(shù)學(xué)和數(shù)字,但如果我們的數(shù)據(jù)集有分類變量,那么在構(gòu)建模型時(shí)可能會(huì)產(chǎn)生麻煩。因此有必要將這些分類變量編碼為數(shù)字。
對(duì)于國家變量:
首先,我們將國家變量轉(zhuǎn)換為分類數(shù)據(jù)。為此,我們將使用預(yù)處理庫中的LabelEncoder()類。
#分類數(shù)據(jù) #for國家變量 從 sklearn.preprocessing 導(dǎo)入 LabelEncoder label_encoder_x = LabelEncoder () x[:, 0]= label_encoder_x.fit_transform(x[:, 0])
輸出:
Out[15]: array([[2, 38.0, 68000.0], [0, 43.0, 45000.0], [1, 30.0, 54000.0], [0, 48.0, 65000.0], [1, 40.0, 65222.22222222222], [2, 35.0, 58000.0], [1, 41.111111111111114, 53000.0], [0, 49.0, 79000.0], [2, 50.0, 88000.0], [0, 37.0, 77000.0]], dtype=object)
解釋:
在上面的代碼中,我們導(dǎo)入了sklearn庫的LabelEncoder類。此類已成功將變量編碼為數(shù)字。
但在我們的例子中,有三個(gè)國家變量,正如我們?cè)谏厦娴妮敵鲋锌吹降?,這些變量被編碼為 0、1 和 2。通過這些值,機(jī)器學(xué)習(xí)模型可以假設(shè)這些變量之間存在某種相關(guān)性。會(huì)產(chǎn)生錯(cuò)誤輸出的變量。因此,為了解決這個(gè)問題,我們將使用虛擬編碼。
虛擬變量:
虛擬變量是那些值為 0 或 1 的變量。值 1 表示該變量在特定列中的存在,其余變量變?yōu)?0。通過虛擬編碼,我們將擁有等于類別數(shù)的列數(shù)。
在我們的數(shù)據(jù)集中,我們有 3 個(gè)類別,因此它將生成具有 0 和 1 值的三列。對(duì)于虛擬編碼,我們將使用預(yù)處理庫的OneHotEncoder類。
#for國家變量 從sklearn.preprocessing導(dǎo)入LabelEncoder、OneHotEncoder label_encoder_x=LabelEncoder() x[:,0]=label_encoder_x.fit_transform(x[:,0]) #虛擬變量的編碼 onehot_encoder=OneHotEncoder(categorical_features=[0]) x=onehot_encoder.fit_transform(x).toarray()
輸出:
array([[0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 3.80000000e+01, 6.80000000e+04], [1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 4.30000000e+01, 4.50000000e+04], [0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 3.00000000e+01, 5.40000000e+04], [1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 4.80000000e+01, 6.50000000e+04], [0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 4.00000000e+01, 6.52222222e+04], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 3.50000000e+01, 5.80000000e+04], [0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 4.11111111e+01, 5.30000000e+04], [1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 4.90000000e+01, 7.90000000e+04], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 5.00000000e+01, 8.80000000e+04], [1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.70000000e+01, 7.70000000e+04]])
正如我們?cè)谏厦娴妮敵鲋锌吹降?,所有變量都被編碼為數(shù)字 0 和 1,并分為三列。
通過單擊 x 選項(xiàng),可以在變量資源管理器部分中更清楚地看到它:
對(duì)于購買的變量:
labelencoder_y = LabelEncoder () y = labelencoder_y .fit_transform(y)
對(duì)于第二個(gè)分類變量,我們將僅使用LableEncoder類的 labelencoder 對(duì)象。這里我們沒有使用OneHotEncoder類,因?yàn)橘徺I的變量只有 yes 或 no 兩個(gè)類別,并且自動(dòng)編碼為 0 和 1。
輸出:
Out[17]:array([0,1,0,0,1,1,0,1,0,1])
view:
6)將數(shù)據(jù)集分為訓(xùn)練集和測(cè)試集
在機(jī)器學(xué)習(xí)數(shù)據(jù)預(yù)處理中,我們將數(shù)據(jù)集分為訓(xùn)練集和測(cè)試集。這是數(shù)據(jù)預(yù)處理的關(guān)鍵步驟之一,因?yàn)橥ㄟ^這樣做,我們可以提高機(jī)器學(xué)習(xí)模型的性能。
假設(shè),如果我們通過數(shù)據(jù)集對(duì)機(jī)器學(xué)習(xí)模型進(jìn)行訓(xùn)練,并通過完全不同的數(shù)據(jù)集對(duì)其進(jìn)行測(cè)試。那么,這會(huì)給我們的模型理解模型之間的相關(guān)性帶來困難。
如果我們的模型訓(xùn)練得很好,它的訓(xùn)練精度也很高,但是我們給它提供了一個(gè)新的數(shù)據(jù)集,那么它的性能就會(huì)下降。因此,我們總是嘗試建立一個(gè)在訓(xùn)練集和測(cè)試數(shù)據(jù)集上都表現(xiàn)良好的機(jī)器學(xué)習(xí)模型。在這里,我們可以將這些數(shù)據(jù)集定義為:
訓(xùn)練集:用于訓(xùn)練機(jī)器學(xué)習(xí)模型的數(shù)據(jù)集子集,我們已經(jīng)知道輸出。
測(cè)試集:用于測(cè)試機(jī)器學(xué)習(xí)模型的數(shù)據(jù)集子集,模型通過使用測(cè)試集來預(yù)測(cè)輸出。
為了分割數(shù)據(jù)集,我們將使用以下代碼行:
#從 sklearn.model_selection 導(dǎo)入 train_test_split x_train,x_test,y_train, y_test = train_test_split (x,y, test_size = 0 .2, random_state = 0 )
解釋:
在上面的代碼中,第一行用于將數(shù)據(jù)集數(shù)組拆分為隨機(jī)訓(xùn)練和測(cè)試子集。
在第二行中,我們使用了四個(gè)變量作為輸出:
x_train:訓(xùn)練數(shù)據(jù)的特征
x_test:測(cè)試數(shù)據(jù)的特征
y_train:訓(xùn)練數(shù)據(jù)的因變量
y_test:測(cè)試數(shù)據(jù)的自變量
在train_test_split()函數(shù)中,我們傳遞了四個(gè)參數(shù),其中前兩個(gè)用于數(shù)據(jù)數(shù)組,test_size用于指定測(cè)試集的大小。test_size 可能是 0.5、.3 或 .2,它告訴我們訓(xùn)練集和測(cè)試集的劃分比例。
最后一個(gè)參數(shù)random_state用于設(shè)置隨機(jī)生成器的種子,以便始終得到相同的結(jié)果,最常用的值為 42。
輸出:
通過執(zhí)行上面的代碼,我們將得到4個(gè)不同的變量,可以在變量資源管理器部分看到。
正如我們?cè)谏蠄D中看到的,x 和 y 變量被分為 4 個(gè)具有相應(yīng)值的不同變量。
7) 特征縮放
特征縮放是機(jī)器學(xué)習(xí)中數(shù)據(jù)預(yù)處理的最后一步。它是一種將數(shù)據(jù)集的自變量標(biāo)準(zhǔn)化在特定范圍內(nèi)的技術(shù)。在特征縮放中,我們將變量放在相同的范圍和相同的比例中,以便沒有任何變量支配其他變量。
考慮以下數(shù)據(jù)集:
正如我們所看到的,年齡和薪水列值不在同一范圍內(nèi)。機(jī)器學(xué)習(xí)模型基于歐幾里德距離,如果我們不縮放變量,那么它將在我們的機(jī)器學(xué)習(xí)模型中引起一些問題。
歐幾里德距離給出為:
如果我們根據(jù)年齡和薪水計(jì)算任意兩個(gè)值,那么薪水值將主導(dǎo)年齡值,并且會(huì)產(chǎn)生不正確的結(jié)果。因此,為了解決這個(gè)問題,我們需要對(duì)機(jī)器學(xué)習(xí)進(jìn)行特征縮放。
機(jī)器學(xué)習(xí)中有兩種執(zhí)行特征縮放的方法:
標(biāo)準(zhǔn)化
正?;?/p>
在這里,我們將對(duì)數(shù)據(jù)集使用標(biāo)準(zhǔn)化方法。
對(duì)于特征縮放,我們將導(dǎo)入sklearn.preprocessing庫的StandardScaler類:
從 sklearn.preprocessing 導(dǎo)入 StandardScaler
現(xiàn)在,我們將為自變量或特征創(chuàng)建StandardScaler類的對(duì)象。然后我們將擬合和轉(zhuǎn)換訓(xùn)練數(shù)據(jù)集。
st_x = 標(biāo)準(zhǔn)縮放器() x_train = st_x .fit_transform(x_train)
對(duì)于測(cè)試數(shù)據(jù)集,我們將直接應(yīng)用transform()函數(shù)而不是fit_transform(),因?yàn)樗呀?jīng)在訓(xùn)練集中完成了。
x_test = st_x .transform(x_test)
輸出:
通過執(zhí)行上面的代碼行,我們將得到 x_train 和 x_test 的縮放值:
x_train:
x_test:
正如我們?cè)谏厦娴妮敵鲋锌吹降?,所有變量都在?-1 到 1 之間縮放。
注意:這里,我們沒有縮放因變量,因?yàn)橹挥袃蓚€(gè)值 0 和 1。但是如果這些變量有更多的值范圍,那么我們還需要縮放這些變量。
結(jié)合所有步驟:
現(xiàn)在,最后,我們可以將所有步驟組合在一起,使完整的代碼更容易理解。
# 導(dǎo)入庫 將 numpy 導(dǎo)入為 nm 將 matplotlib.pyplot 導(dǎo)入為 mtp 將 pandas 導(dǎo)入為 pd #導(dǎo)入數(shù)據(jù)集 data_set = pd .read_csv('數(shù)據(jù)集.csv') #提取自變量 x = data_set .iloc[:, :-1].values #提取因變量 y = data_set .iloc[:, 3].values #處理缺失數(shù)據(jù)(用平均值替換缺失數(shù)據(jù)) 從 sklearn.preprocessing 導(dǎo)入 Imputer imputer = Imputer (missing_values = 'NaN' , 策略= '平均值' , 軸 = 0 ) #將輸入對(duì)象擬合到獨(dú)立變量x。 imputer imputer = imputer.fit(x[:, 1:3]) #用計(jì)算出的平均值替換缺失數(shù)據(jù) x[:, 1:3]= imputer.transform(x[:, 1:3]) #for 國家變量 從 sklearn.preprocessing 導(dǎo)入 LabelEncoder、OneHotEncoder label_encoder_x = LabelEncoder () x[:, 0]= label_encoder_x.fit_transform(x[:, 0]) #虛擬變量的編碼 onehot_encoder = OneHotEncoder ( categorical_features = [0]) x = onehot_encoder .fit_transform(x).toarray() #購買變量的編碼 labelencoder_y = LabelEncoder () y = labelencoder_y .fit_transform(y) # 將數(shù)據(jù)集分為訓(xùn)練集和測(cè)試集。 從 sklearn.model_selection 導(dǎo)入 train_test_split x_train,x_test,y_train, y_test = train_test_split (x,y, test_size = 0 .2, random_state = 0 ) #數(shù)據(jù)集的特征縮放 從 sklearn.preprocessing 導(dǎo)入 StandardScaler st_x = 標(biāo)準(zhǔn)縮放器() x_train = st_x .fit_transform(x_train) x_test = st_x .transform(x_test)
在上面的代碼中,我們將所有數(shù)據(jù)預(yù)處理步驟包含在一起。但有些步驟或代碼行并不是所有機(jī)器學(xué)習(xí)模型都必需的。因此,我們可以將它們從我們的代碼中排除,使其可重用于所有模型。
審核編輯:彭菁
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7035瀏覽量
89045 -
模型
+關(guān)注
關(guān)注
1文章
3244瀏覽量
48847 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68625 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8418瀏覽量
132654 -
python
+關(guān)注
關(guān)注
56文章
4797瀏覽量
84694
原文標(biāo)題:機(jī)器學(xué)習(xí)中的數(shù)據(jù)預(yù)處理
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論