
R語言與函數(shù)估計學(xué)習(xí)筆記(核方法與局部多項式)
非參數(shù)方法
用于函數(shù)估計的非參數(shù)方法大致上有三種:核方法、局部多項式方法、樣條方法。
非參的函數(shù)估計的優(yōu)點在于穩(wěn)健,對模型沒有什么特定的假設(shè),只是認(rèn)為函數(shù)光滑,避免了模型選擇帶來的風(fēng)險;但是,表達式復(fù)雜,難以解釋,計算量大是非參的一個很大的毛病。所以說使用非參有風(fēng)險,選擇需謹(jǐn)慎。
非參的想法很簡單:函數(shù)在觀測到的點取觀測值的概率較大,用x附近的值通過加權(quán)平均的辦法估計函數(shù)f(x)的值。
核方法
當(dāng)加權(quán)的權(quán)重是某一函數(shù)的核(關(guān)于“核”的說法可參見之前的博文《R語言與非參數(shù)統(tǒng)計(核密度估計)》),這種方法就是核方法,常見的有Nadaraya-Watson核估計與Gasser-Muller核估計方法,也就是很多教材里談到的NW核估計與GM核估計,這里我們還是不談核的選擇,將一切的核估計都默認(rèn)用Gauss核處理。
NW核估計形式為:
GM核估計形式為:
式中
x <- seq(-1, 1, length = 20)
y <- 5 * x * cos(5 * pi * x)
h <- 0.088
fx.hat <- function(z, h) {
dnorm((z - x)/h)/h
}
KSMOOTH <- function(h, y, x) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
a <- fx.hat(x[i], h)
s.hat[i] <- sum(y * a/sum(a))
}
return(s.hat)
}
ksmooth.val <- KSMOOTH(h, y, x)
plot(x, y, xlab = "Predictor", ylab = "Response")
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 2, add = T)
lines(x, ksmooth.val, type = "l")
可以看出,核方法基本估計出了函數(shù)的形狀,但是效果不太好,這個是由于樣本點過少導(dǎo)致的,我們可以將樣本容量擴大一倍,看看效果:
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
h <- 0.055
fx.hat <- function(z, h) {
dnorm((z - x)/h)/h
}
NWSMOOTH <- function(h, y, x) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
a <- fx.hat(x[i], h)
s.hat[i] <- sum(y * a/sum(a))
}
return(s.hat)
}
NWsmooth.val <- NWSMOOTH(h, y, x)
plot(x, y, xlab = "Predictor", ylab = "Response", col = 1)
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 1, add = T, col = 1)
lines(x, NWsmooth.val, lty = 2, col = 2)
A <- data.frame(x = seq(-1, 1, length = 1000))
model.linear <- lm(y ~ poly(x, 9))
lines(seq(-1, 1, length = 1000), predict(model.linear, A), lty = 3, col = 3)
letters <- c("NW method", "orignal model", "9 order poly-reg")
legend("bottomright", legend = letters, lty = c(2, 1, 3), col = c(2, 1, 3),
cex = 0.5)
可以看到估計效果還是很好的,至少比基函數(shù)的辦法要好一些。那么我們來看看GM核方法:
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
h <- 0.055
GMSMOOTH <- function(y, x, h) {
n <- length(y)
s <- c(-Inf, 0.5 * (x[-n] + x[-1]), Inf)
s.hat <- rep(0, n)
for (i in 1:n) {
fx.hat <- function(z, h, x) {
dnorm((x - z)/h)/h
}
a <- y[i] * integrate(fx.hat, s[i], s[i + 1], h = h, x = x[i])$value
s.hat[i] <- sum(a)
}
return(s.hat)
}
GMsmooth.val <- GMSMOOTH(y, x, h)
plot(x, y, xlab = "Predictor", ylab = "Response", col = 1)
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 1, add = T, col = 1)
lines(x, GMsmooth.val, lty = 2, col = 2)
A <- data.frame(x = seq(-1, 1, length = 1000))
model.linear <- lm(y ~ poly(x, 9))
lines(seq(-1, 1, length = 1000), predict(model.linear, A), lty = 3, col = 3)
letters <- c("GM method", "orignal model", "9 order poly-reg")
legend("bottomright", legend = letters, lty = c(2, 1, 3), col = c(2, 1, 3),
cex = 0.5)
我們來看看兩個核估計辦法的差異:
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
h <- 0.055
fx.hat <- function(z, h) {
dnorm((z - x)/h)/h
}
NWSMOOTH <- function(h, y, x) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
a <- fx.hat(x[i], h)
s.hat[i] <- sum(y * a/sum(a))
}
return(s.hat)
}
NWsmooth.val <- NWSMOOTH(h, y, x)
GMSMOOTH <- function(y, x, h) {
n <- length(y)
s <- c(-Inf, 0.5 * (x[-n] + x[-1]), Inf)
s.hat <- rep(0, n)
for (i in 1:n) {
fx.hat <- function(z, h, x) {
dnorm((x - z)/h)/h
}
a <- y[i] * integrate(fx.hat, s[i], s[i + 1], h = h, x = x[i])$value
s.hat[i] <- sum(a)
}
return(s.hat)
}
GMsmooth.val <- GMSMOOTH(y, x, h)
plot(x, y, xlab = "Predictor", ylab = "Response", col = 1)
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 1, add = T, col = 1)
lines(x, NWsmooth.val, lty = 2, col = 2)
lines(x, GMsmooth.val, lty = 3, col = 3)
letters <- c("orignal model", "NW method", "GM method")
legend("bottomright", legend = letters, lty = 1:3, col = 1:3, cex = 0.5)
從圖中可以看到NW估計的方差似乎小些,事實也確實如此,GM估計的漸進方差約為NW估計的1.5倍。但是GM估計解決了一些計算的難題。
我們最后還是來展示不同窗寬的選擇對估計的影響(這里以NW估計為例):
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
fx.hat <- function(z, h) {
dnorm((z - x)/h)/h
}
NWSMOOTH <- function(h, y, x) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
a <- fx.hat(x[i], h)
s.hat[i] <- sum(y * a/sum(a))
}
return(s.hat)
}
h <- 0.025
NWsmooth.val0 <- NWSMOOTH(h, y, x)
h <- 0.05
NWsmooth.val1 <- NWSMOOTH(h, y, x)
h <- 0.1
NWsmooth.val2 <- NWSMOOTH(h, y, x)
h <- 0.2
NWsmooth.val3 <- NWSMOOTH(h, y, x)
h <- 0.3
NWsmooth.val4 <- NWSMOOTH(h, y, x)
plot(x, y, xlab = "Predictor", ylab = "Response", col = 1)
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 1, add = T, col = 1)
lines(x, NWsmooth.val0, lty = 2, col = 2)
lines(x, NWsmooth.val1, lty = 3, col = 3)
lines(x, NWsmooth.val2, lty = 4, col = 4)
lines(x, NWsmooth.val3, lty = 5, col = 5)
lines(x, NWsmooth.val4, lty = 6, col = 6)
letters <- c("orignal model", "h=0.025", "h=0.05", "h=0.1", "h=0.2", "h=0.3")
legend("bottom", legend = letters, lty = 1:6, col = 1:6, cex = 0.5)
可以看到窗寬越大,估計越光滑,誤差越大,窗寬越小,估計越不光滑,但擬合優(yōu)度有提高,卻也容易過擬合。
窗寬怎么選,一個可行的辦法就是CV,通俗的講就是取一個觀測做測試集,剩下的做訓(xùn)練集,看NMSE。R代碼如下:
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
# h<-0.055
NWSMOOTH <- function(h, y, x, z) {
n <- length(y)
s.hat <- rep(0, n)
s.hat1 <- rep(0, n)
for (i in 1:n) {
s.hat[i] <- dnorm((x[i] - z)/h)/h * y[i]
s.hat1[i] <- dnorm((x[i] - z)/h)/h
}
z.hat <- sum(s.hat)/sum(s.hat1)
return(z.hat)
}
CVRSS <- function(h, y, x) {
cv <- NULL
for (i in seq(x)) {
cv[i] <- (y[i] - NWSMOOTH(h, y[-i], x[-i], x[i]))^2
}
mean(cv)
}
h <- seq(0.01, 0.2, by = 0.005)
cvrss.val <- rep(0, length(h))
for (i in seq(h)) {
cvrss.val[i] <- CVRSS(h[i], y, x)
}
plot(h, cvrss.val, type = "b")
從圖中我們可以見到CV值在0.01到0.05的變化都不大,這時,我們應(yīng)該選擇較大的h,使得函數(shù)較為光滑,但是0.05后,cv變化較大,說明我們選擇窗寬也不能過大,否則也會出毛病的。那么是不是h越小越好呢?雖然上面一個例子給了我們這樣一個錯覺,我們下面這個例子就可以打破它,數(shù)據(jù)來自《computational statistics》一書的essay data一例。
easy <- read.table("D:/R/data/easysmooth.dat", header = T)
x <- easy$X
y <- easy$Y
NWSMOOTH <- function(h, y, x, z) {
n <- length(y)
s.hat <- rep(0, n)
s.hat1 <- rep(0, n)
for (i in 1:n) {
s.hat[i] <- dnorm((x[i] - z)/h)/h * y[i]
s.hat1[i] <- dnorm((x[i] - z)/h)/h
}
z.hat <- sum(s.hat)/sum(s.hat1)
return(z.hat)
}
CVRSS <- function(h, y, x) {
cv <- NULL
for (i in seq(x)) {
cv[i] <- (y[i] - NWSMOOTH(h, y[-i], x[-i], x[i]))^2
}
mean(cv)
}
h <- seq(0.01, 0.3, by = 0.02)
cvrss.val <- rep(0, length(h))
for (i in seq(h)) {
cvrss.val[i] <- CVRSS(h[i], y, x)
}
plot(h, cvrss.val, type = "b")
從上圖就可以看到,最佳窗寬約為0.15,而不是0.01.
和樹回歸類似,我們的核方法就是提供了一個常數(shù)來漸進這個函數(shù),我們這里仍然可以考慮模型樹的想法,用一階或者高階多項式來作加權(quán)估計,這就有了局部多項式估計。
局部多項式
估計的想法是認(rèn)為未知函數(shù)f(x)在近鄰鄰域內(nèi)可由某一多項式近似(這是Taylor公式的結(jié)果),在x0的鄰域內(nèi)最小化:
具體做法為:
(1)對于每個xi,以該點為中心,計算出對應(yīng)點處的權(quán)重Kh(xi?x);
(2)采用加權(quán)最小二乘法(WLS)估計其參數(shù),并用得到的模型估計該結(jié)點對應(yīng)的x值對應(yīng)y值,作為y|xi的估計值(只要這一個點的估計值);
(3)估計下一個點xj;
(4)將每個y|xi的估計值連接起來。
我們這里以《computational statistics》一書的essay data為例來說明局部多項式估計
easy <- read.table("D:/R/data/easysmooth.dat", header = T)
x <- easy$X
y <- easy$Y
h <- 0.16
## FUNCTIONS USES HAT MATRIX
LPRSMOOTH <- function(y, x, h) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
weight <- dnorm((x - x[i])/h)
mod <- lm(y ~ x, weights = weight)
s.hat[i] <- as.numeric(predict(mod, data.frame(x = x[i])))
}
return(s.hat)
}
lprsmooth.val <- LPRSMOOTH(y, x, h)
s <- function(x) {
(x^3) * sin((x + 3.4)/2)
}
x.plot <- seq(min(x), max(x), length.out = 1000)
y.plot <- s(x.plot)
plot(x, y, xlab = "Predictor", ylab = "Response")
lines(x.plot, y.plot, lty = 1, col = 1)
lines(x, lprsmooth.val, lty = 2, col = 2)
我們回到最開始我們提到的三角函數(shù)的例子,我們可以看到:
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
## FUNCTIONS
LPRSMOOTH <- function(y, x, h) {
n <- length(y)
s.hat <- rep(0, n)
for (i in 1:n) {
weight <- dnorm((x - x[i])/h)
mod <- lm(y ~ x, weights = weight)
s.hat[i] <- as.numeric(predict(mod, data.frame(x = x[i])))
}
return(s.hat)
}
h <- 0.15
lprsmooth.val1 <- LPRSMOOTH(y, x, h)
h <- 0.066
lprsmooth.val2 <- LPRSMOOTH(y, x, h)
plot(x, y, xlab = "Predictor", ylab = "Response")
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1, ylim = c(-15.5, 15.5), lty = 1, add = T, col = 1)
lines(x, lprsmooth.val1, lty = 2, col = 2)
lines(x, lprsmooth.val2, lty = 3, col = 3)
letters <- c("orignal model", "h=0.15", "h=0.66")
legend("bottom", legend = letters, lty = 1:3, col = 1:3, cex = 0.5
R中提供了很多的函數(shù)包來做非參數(shù)回歸,常用的有:KernSmooth包的函數(shù)locpoly(),locpol的locpol(),locCteSmootherC()以及l(fā)ocfit的locfit().具體的參數(shù)設(shè)置較為簡單,這里就不多說了。我們以開篇的三角函數(shù)模型的例子為例來看看如何使用它們:
library(KernSmooth) #函數(shù)locpoly()
library(locpol) #locpol(); locCteSmootherC()
library(locfit) #locfit()
x <- seq(-1, 1, length = 40)
y <- 5 * x * cos(5 * pi * x)
f <- function(x) 5 * x * cos(5 * pi * x)
curve(f, -1, 1)
points(x, y)
fit <- locpoly(x, y, bandwidth = 0.066)
lines(fit, lty = 2, col = 2)
d <- data.frame(x = x, y = y)
r <- locfit(y ~ x, d) #一般來說,locfit函數(shù)自動選的窗寬偏大,函數(shù)較光滑
lines(r, lty = 3, col = 3)
xeval <- seq(-1, 1, length = 10)
cuest <- locCuadSmootherC(d$x, d$y, xeval, 0.066, gaussK)
cuest
## x beta0 beta1 beta2 den
## 1 -1.0000 5.0858 -35.152 -222.58 0.07571
## 2 -0.7778 -3.3233 11.966 514.42 4.22454
## 3 -0.5556 1.9804 -16.219 -279.47 4.26349
## 4 -0.3333 -0.8416 13.137 83.37 4.26349
## 5 -0.1111 0.1924 -4.983 27.90 4.26349
## 6 0.1111 -0.1924 -4.983 -27.90 4.26349
## 7 0.3333 0.8416 13.137 -83.37 4.26349
## 8 0.5556 -1.9804 -16.219 279.47 4.26349
## 9 0.7778 3.3233 11.966 -514.42 4.22454
## 10 1.0000 -5.0858 -35.152 222.58 0.07571
關(guān)于局部多項式估計的想法還有很多,比如我們只考慮近鄰的數(shù)據(jù)作最小二乘估計,再比如我們可以修改權(quán)重,使得我們的窗寬與近鄰點的距離有關(guān),再比如,我們可以考慮不采用最小二乘做優(yōu)化,而是對最小二乘加上一點點的懲罰……我們將第一個想法稱之為running line,第二個想法稱之為loess,第三個想法依據(jù)你的懲罰方式不同有不同的說法。我們將running line的R程序給出如下:
RLSMOOTH <- function(k, y, x) {
n <- length(y)
s.hat <- rep(0, n)
b <- (k - 1)/2
if (k > 1) {
for (i in 1:(b + 1)) {
xi <- x[1:(b + i)]
xi <- cbind(rep(1, length(xi)), xi)
hi <- xi %*% solve(t(xi) %*% xi) %*% t(xi)
s.hat[i] <- y[1:(b + i)] %*% hi[i, ]
xi <- x[(n - b - i + 1):n]
xi <- cbind(rep(1, length(xi)), xi)
hi <- xi %*% solve(t(xi) %*% xi) %*% t(xi)
s.hat[n - i + 1] <- y[(n - b - i + 1):n] %*% hi[nrow(hi) - i + 1,
]
}
for (i in (b + 2):(n - b - 1)) {
xi <- x[(i - b):(i + b)]
xi <- cbind(rep(1, length(xi)), xi)
hi <- xi %*% solve(t(xi) %*% xi) %*% t(xi)
s.hat[i] <- y[(i - b):(i + b)] %*% hi[b + 1, ]
}
}
if (k == 1) {
s.hat <- y
}
return(s.hat)
}
我們也一樣可以對running line做局部多項式回歸,代碼如下:
WRLSMOOTH <- function(k, y, x, h) {
n <- length(y)
s.hat <- rep(0, n)
b <- (k - 1)/2
if (k > 1) {
for (i in 1:(b + 1)) {
xi <- x[1:(b + i)]
xi <- cbind(rep(1, length(xi)), xi)
hi <- xi %*% solve(t(xi) %*% xi) %*% t(xi)
s.hat[i] <- y[1:(b + i)] %*% hi[i, ]
xi <- x[(n - b - i + 1):n]
xi <- cbind(rep(1, length(xi)), xi)
hi <- xi %*% solve(t(xi) %*% xi) %*% t(xi)
s.hat[n - i + 1] <- y[(n - b - i + 1):n] %*% hi[nrow(hi) - i + 1,
]
}
for (i in (b + 2):(n - b - 1)) {
xi <- x[(i - b):(i + b)]
weight <- dnorm((xi - x[i])/h)
mod <- lm(y[(i - b):(i + b)] ~ xi, weights = weight)
s.hat[i] <- as.numeric(predict(mod, data.frame(xi = x[i])))
}
}
if (k == 1) {
s.hat <- y
}
return(s.hat)
}
R中也提供了函數(shù)lowess()來做loess回歸。我們這里不妨以essay data為例,看看這三個估計有多大的差別:
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預(yù)測分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢預(yù)判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預(yù)測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點,而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經(jīng)濟蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對策略? 長短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨特的門控機制,在 ...
2025-07-07統(tǒng)計學(xué)方法在市場調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場調(diào)研是企業(yè)洞察市場動態(tài)、了解消費者需求的重要途徑,而統(tǒng)計學(xué)方法則是市場調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03