Yazar: Matthew Smith
Çeviri: Zhang Ruonan
Düzeltme: Wu Jindi
Bu makale Yaklaşık 6700 kelime , Okumanız tavsiye edilir 10 dakika
Bu makale, birden çok makine öğrenimi modeli grubunu eğitmek için Iris veri kümesini kullanır ve büyük miktarda uygun veriyi tahmin ederek her modelin karar sınırını çizer.
Etiket: Makine Öğrenimi
Iris veri kümesini kullanarak bir dizi makine öğrenimi modeli eğittim, verilerdeki uç değerlerden yeni veri noktalarını sentezledim ve karar sınırlarını çizmek için birçok makine öğrenimi modelini test ettim, bu da bu sınırlara dayalı olarak 2B alanda tahminlerde bulunabilir , Bu, amacı netleştirmek ve farklı makine öğrenimi modellerinin nasıl tahminler yaptığını anlamak için yararlıdır.
Makine öğrenimi modelleri geleneksel ekonometrik modellerden daha iyi performans gösterebilir.Bu yeni bir şey değil, ancak araştırmanın bir parçası olarak, bazı modellerin neden ve nasıl sınıflandırma tahminleri yaptığını açıklamak istiyorum. İkili sınıflandırma modelimin dayandığı karar sınırını, yani verilerin sınıflandırma tahmini için görüntülendiği bölüm alanını göstermek istiyorum. Problem ve kod, bazı ayarlamalardan sonra çok sınıflı problemlere de uygulanabilir.
Önce bir dizi paketi yükleyin ve ardından log-olasılıkları daha sonra lojistik olasılık işlevine dönüştürmek için yeni bir lojistik işlev oluşturun.
library (dplyr) library (patchwork) library (ggplot2) library (knitr) library (kableExtra) library (purrr) library (stringr) library (tidyr) library (xgboost) library (lightgbm) library (keras) library (tidyquant) ## ################### Bazı işlevleri önceden tanımlayınlogit2prob < -function (logit) {oran < -exp (logit) probu < -odds / (1 + oran) getiri (prob)}Kullandığım iris veri seti, İngiliz istatistikçi Ronald Fisher tarafından 1936'da toplanan 3 farklı bitki değişkeni hakkında bilgi içeriyor. Veri seti, 33 farklı türü (Setosa, Virginica ve Versicolor) ayırt edebilen 4 bitki türünün farklı özelliklerini içerir. Ancak benim sorunumun çoklu sınıflandırma problemine değil, ikili sınıflandırma problemine ihtiyacı var. Aşağıdaki kodda, iris verilerini içe aktardım ve bir bitki türü olan virginica'yı birden fazla sınıflandırmadan ikili bir sınıflandırma problemine dönüştürmek için sildim.
veri (iris) df < -iris% > % filter (Türler! = "virginica")% > % mutate (Türler = + (Türler == "versicolor")) str (df) ## 'data.frame': 5 değişken için 100 gözlem: ## $ Sepal.Uzunluk: num 5.14.94.74.65 5.44.65 4.44.9 ... ## $ Ayrı Genişlik: num 3.53 3.23.13.63.93.43.42.93.1 ... ## $ Yaprağı Uzunluk: num 1.41.41.31.51.41.71.41.51.41.5 ... ## $ Petal.Width: num 0.20.20.20.20.20.40.30.20.20.1 ... ## $ Türler: int 00 00 00 00 00 ...Verileri çizmek için önce ggplot kullanıyorum.Aşağıda saklanan ggplot nesnelerinde, her grafik için sadece x ve y değişken seçimleri değiştirilir.
plt1 < -df% > % ggplot (aes (x = Sepal.Width, y = Sepal.Length, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt2 < -df% > % ggplot (aes (x = Petal.Length, y = Sepal.Length, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt3 < -df% > % ggplot (aes (x = Petal.Width, y = Sepal.Length, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt3 < -df% > % ggplot (aes (x = Sepal.Length, y = Sepal.Width, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt4 < -df% > % ggplot (aes (x = Petal.Length, y = Sepal.Width, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt5 < -df% > % ggplot (aes (x = Petal.Width, y = Sepal.Width, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none") plt6 < -df% > % ggplot (aes (x = Petal.Width, y = Sepal.Length, color = factor (Species))) + geom_point (size = 4) + theme_bw (base_size = 15) + theme (legend.position = "none")Ayrıca ggplot sonuçlarını görüntülemeyi kolaylaştırmak için yeni patchwork paketini kullandım. Aşağıdaki kod, grafiğimizi çok basit bir şekilde çizer (üstteki 1 grafik, ızgara alanının uzunluğunu kaplar, 2 orta boyutlu grafik, başka bir tek grafik ve altta 2 diğer grafik)
(plt1) / (plt2 + plt3)Ya da çizimi istediğimiz şekilde yeniden düzenleyebilir ve aşağıdaki şekillerde çizebiliriz:
(plt1 + plt2) / (plt5 + plt6)Bence bu iyi görünüyor.
Amacım, bu iki bitki türünü ayırt etmek için bir sınıflandırma algoritması oluşturmak ve ardından modelin bu tür tahminleri nasıl yaptığını daha iyi anlamak için karar sınırını hesaplamak. Her değişken kombinasyonu için bir karar sınırı haritası oluşturmak amacıyla, verilerde farklı değişken kombinasyonlarına ihtiyacımız var.
var_combos < -expand.grid (sütun adları (df), sütun adları (df))% > % filtre (! Var1 == Var2) var_combos% > % kafa ()% > % kable (caption = "Değişken Kombinasyonları", kaçış = F ,, rakamlar = 2)% > % kable_styling (bootstrap_options = c ("çizgili", "vurgulu", "yoğunlaştırılmış", "duyarlı"), font_size = 9, fixed_thead = T, full_width = F)% > % scroll_box (genişlik = "% 100", yükseklik = "200 piksel")Daha sonra, bir liste (her kombinasyon için bir liste) oluşturmak için yukarıdaki farklı değişken kombinasyonlarını kullanacağım ve listeye değerler atamak için sentetik verileri (veya her değişken kombinasyonunun minimumdan maksimuma olan verilerini) kullanacağım. Bu, tahminler yapmak ve karar sınırları oluşturmak için sentetik test verilerimiz olarak hizmet edecektir.
Bu grafiklerin sonunda iki boyutlu olacağı unutulmamalıdır, bu nedenle makine öğrenimi modelini yalnızca iki değişken üzerinde eğitiyoruz, ancak bu iki değişkenin her kombinasyonu için, bunlar, boundary_lists veri çerçevesindeki ilk ikisi olacak Değişkenler.
border_lists < -map2 (.x = var_combos $ Var1, .y = var_combos $ Var2, ~ seçin (df, .x, .y)% > % özetleme (minX = min (., na.rm = DOĞRU), maksX = maks (., na.rm = DOĞRU), minY = min (., na.rm = DOĞRU), maksY = maks (., na. rm = DOĞRU)))% > % eşleme (., ~ tibble (x = seq (.x $ minX, .x $ maxX, length.out = 200), y = seq (.x $ minY, .x $ maxY, length.out = 200), ))% > % harita (., ~ tibble (xx = rep (.x $ x, her biri = 200), yy = rep (.x $ y, time = 200)))% > % map2 (., asplit (var_combos, 1), ~ .x% > % set_names (.y))İlk iki listenin ilk dört gözleminin nasıl olduğunu görebiliriz:
boundary_lists% > % map (., ~ head (., 4))% > % head (2) ## ## # Bir tibble: 4 x 2 ## Sepal.Width Sepal.Length ## < dbl > < dbl > ## 12 4.3 ## 22 4.31 ## 32 4.33 ## 42 4.34 #### ## # Bir tibble: 4 x 2 ## Petal.Length Sepal.Length ## < dbl > < dbl > ## 11 4.3 ## 21 4.31 ## 31 4.33 ## 41 4.34boundary_lists% > % map (., ~ head (., 4))% > % tail (2) ## ## # Bir tibble: 4 x 2 ## Sepal.Width Petal.Width ## < dbl > < dbl > ## 12 0.1 ## 22 0.109 ## 32 0.117 ## 42 0.126 #### ## # A tibble: 4 x 2 ## Petal.Length Petal.Width ## < dbl > < dbl > ## 11 0.1 ## 21 0.109 ## 31 0.117 ## 41 0.126Artık test için simülasyon verilerini oluşturduğumuza göre, modeli gerçek gözlemlere dayalı olarak eğitmek istiyorum. Aşağıdaki modeli eğitmek için yukarıdaki şekildeki her veri noktasını kullanacağım:
Yan not: Derin öğrenme / Keras / Tensorflow konusunda uzman değilim, bu yüzden daha iyi karar sınırları üreten daha iyi modeller olduğuna inanıyorum, ancak farklı makine öğrenimi modellerini eğitmek için purrr ve map kullanmak çok ilginç.
################################################ ################################################ ################################################ ################# params_lightGBM < -list (# amaç = "binary", # metric = "auc", # min_data = 1 #) # Light GBM'yi yüklemek için RStudio terminalinizde aşağıdakileri deneyin # git clone --recursive https://github.com/microsoft / LightGBM # cd LightGBM # Rscript build_r.Rmodels_list < -var_combos% > % mutate (modeln = str_c ('mod', row_number ()))% > % pmap (~ {xname = ..1 yname = ..2 modelname = ..3 df% > % select (Türler, xname, yname)% > % group_by (grp = 'grp')% > % yuva ()% > % mutate (modeller = eşleme (veri, ~ {liste (# Lojistik Model Model_GLM = {glm (Türler ~., veri = .x, aile = iki terimli (link = 'logit')))}, # Destek Vektör Makinesi (doğrusal) Model_SVM_Linear = {e1071 :: svm (Türler ~., Veri = .x, tip = 'C-sınıflandırma', çekirdek = 'doğrusal')}, # Destek Vektör Makinesi (polinom) Model_SVM_Polynomial = {e1071 :: svm (Türler ~ ., data = .x, type = 'C-sınıflandırma', kernel = 'polinom')}, # Destek Vektör Makinesi (sigmoid) Model_SVM_radial = {e1071 :: svm (Türler ~., veri = .x, tür = ' C-sınıflandırma ', kernel =' sigmoid ')}, # Destek Vektör Makinesi (radyal) Model_SVM_radial_Sigmoid = {e1071 :: svm (Türler ~., Veri = .x, tür =' C-sınıflandırma ', çekirdek =' radyal ' )}, # Random Forest Model_RF = {randomForest :: randomForest (formül = as.factor (Türler) ~., Data =.)}, # Extreme Gradient Arttırma Modeli_XGB = {xgboost (amaç = 'binary: lojistik', eval_metric = 'auc', data = as.matrix (.x), label = as.matrix (.x $ Türler), # ikili değişken nrounds = 10) }, # Kera Sinir Ağı Model_Keras = {mod < -keras_model_sequential ()% > % layer_dense (birimler = 2, aktivasyon = 'relu', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'sigmoid') mod% > % derleme (kayıp = 'binary_crossentropy', optimizer_sgd (lr = 0.01, momentum = 0.9), metrics = c ('doğruluk')) fit (mod, x = as.matrix (.x), y = to_categorical (.x $ Türler, 2), epochs = 5, batch_size = 5, validation_split = 0) print (modelname) assign (modelname, mod)}, # Kera Neural Network Model_Keras_2 = {mod < -keras_model_sequential ()% > % layer_dense (birimler = 2, aktivasyon = 'relu', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'doğrusal', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'sigmoid') mod% > % derleme (kayıp = 'binary_crossentropy', optimizer_sgd (lr = 0.01, momentum = 0.9), metrics = c ('doğruluk')) fit (mod, x = as.matrix (.x), y = to_categorical (.x $ Türler, 2), epochs = 5, batch_size = 5, validation_split = 0) print (modelname) assign (modelname, mod)}, # Kera Neural Network Model_Keras_3 = {mod < -keras_model_sequential ()% > % layer_dense (birimler = 2, aktivasyon = 'relu', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'relu', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'doğrusal', input_shape = 2)% > % layer_dense (birimler = 2, aktivasyon = 'sigmoid') mod% > % derleme (kayıp = 'binary_crossentropy', optimizer_sgd (lr = 0.01, momentum = 0.9), metrics = c ('doğruluk')) fit (mod, x = as.matrix (.x), y = to_categorical (.x $ Türler, 2), epochs = 5, batch_size = 5, validation_split = 0) print (modelname) assign (modelname, mod)}, # LightGBM model Model_LightGBM = {lgb.train (data = lgb.Dataset (data = as.matrix (.x), label = .x $ Türler), amaç = 'ikili', metrik = 'auc', min_data = 1 #params = params_lightGBM, #learning_rate = 0.1)})}))})% > % eşleme (., ~ unlist (., özyinelemeli = YANLIŞ))Artık eğitimli model ve tahminlere sahip olduğumuza göre, bu tahminleri ggplot ile görselleştirme için verilere geri koyabilir ve ardından dizgi için patchwork paketini kullanabiliriz.
plot_data < -map2 (.x = border_lists, .y = map (models_predict, ~ map (., ~ tibble (.))), ~ bind_cols (.x, .y)) isimleri (plot_data) < -map_chr (plot_data, ~ c (yapıştır (sütun adları (.), "ve", sütun adları (.), sep = "_")))Artık tahminlerimiz olduğuna göre ggplots oluşturabiliriz.
ggplot_lists < -plot_data% > % map (., ~ select (., -contains ("Model"))% > % pivot_longer (cols = contains ("Tahmin"), names_to = "Model", values_to = "Tahmin"))% > % map (.x =., ~ ggplot () + geom_point (aes (x = !! rlang :: sym (colnames (.x)), y = !! rlang :: sym (colnames (.x)), color = faktör (!! rlang :: sym (sütun adları (.x)))), veri = .x) + geom_contour (aes (x = !! rlang :: sym (sütun adları (.x)), y = !! rlang :: sym (sütun adları (.x)), z = !! rlang :: sym (sütun adları (.x))), veri = .x) + geom_point (aes (x = !! rlang :: sym (sütun adları (. x)), y = !! rlang :: sym (colnames (.x)), color = factor (!! rlang :: sym (colnames (df))) # bu durum değişkeni), size = 8, data = df) + geom_point (aes (x = !! rlang :: sym (colnames (.x)), y = !! rlang :: sym (colnames (.x))), size = 8, şekil = 1, veri = df) + facet_wrap (~ Model) + theme_bw (base_size = 25) + tema (legend.position = "yok"))Tüm farklı karar sınırları kombinasyonlarını çizin. Not: Yukarıdaki kod konsolunuzda daha iyi çalışacaktır.Bu blog gönderisini programlamak için kodu kullandığımda görüntü çok küçük. Bu nedenle, model ve değişken kombinasyonlarının örnekleri için ayrı diyagramlar sağladım.
Öncelikle hedef değişkenlerimiz olan ilk iki sütunu seçmem gerekiyor (Petal.Width, Petal.Length, Sepal.Width ve Sepal.Length). Ardından, her bir sütunun örneklerini rastgele örneklemek istiyorum (yani, farklı makine öğrenimi modellerinin tahmin sonuçları).
plot_data_sampled < -plot_data% > % map (., ~ select (., -contains ("Model"))% > % seçin (., c (1: 2), örnek (sütun adları (.), 2))% > % pivot_longer (cols = contains ("Tahmin"), names_to = "Model", values_to = "Tahmin"))Daha sonra rastgele bir liste çizerek çizebilirim.
plot_data_sampled% > % rlist :: list.sample (1)% > % map (.x =., ~ ggplot () + geom_point (aes (x = !! rlang :: sym (colnames (.x)), y = !! rlang :: sym (colnames (.x)), color = faktör (!! rlang :: sym (sütun adları (.x)))), veri = .x) + geom_contour (aes (x = !! rlang :: sym (sütun adları (.x)), y = !! rlang :: sym (sütun adları (.x)), z = !! rlang :: sym (sütun adları (.x))), veri = .x) + geom_point (aes (x = !! rlang :: sym (sütun adları (. x)), y = !! rlang :: sym (colnames (.x)), color = factor (!! rlang :: sym (colnames (df))) # bu durum değişkeni), size = 3, data = df) + geom_point (aes (x = !! rlang :: sym (colnames (.x)), y = !! rlang :: sym (colnames (.x))), size = 3, şekil = 1, veri = df) + facet_wrap (~ Model) + #coord_flip () + theme_tq (base_family = "serif") + theme (# boy.ratio = 1, axis.line.y = element_blank (), axis.ticks.y = element_blank (), legend.position = "bottom", # legend.title = element_text (size = 20), # legend.text = element_text (size = 10), axis.title = element_text (size = 20), axis.text = element_text (size = "15"), strip.text.x = element_text (size = 15), plot.title = element_tex t (size = 30, hjust = 0.5), strip.background = element_rect (fill = 'darkred'), panel.background = element_blank (), panel.grid.major = element_blank (), panel.grid.minor = element_blank ( ), # axis.text.x = element_text (açı = 90), axis.text.y = element_text (açı = 90, hjust = 0.5), # axis.title.x = element_blank () legend.title = element_blank () , legend.text = element_text (size = 20))) ## $ Sepal.Width_and_Petal.Length ## Uyarı: Satır indeksleri 0 ile satır sayısı (0) arasında olmalıdır. Bir satır indeksi olarak "NA" kullanın satır "NA" değerleriyle dolu. ## Bu uyarı oturum başına bir kez görüntülenir.Diğer bazı rastgele modeller:
## $ Sepal.Width_and_Sepal.Length ## $ Sepal.Width_and_Sepal.Length ## $ Petal.Length_and_Sepal.Length ## $ Petal.Width_and_Petal.Length ## $ Petal.Length_and_Petal.Width ## grDevices :: contourLines'da uyarı (x = sort (unique (data $ x)), y = ## sort (unique (data $ y))) ,: todos los valores de z son iguales ## Uyarı: Kontur verileri oluşturmak mümkün değilGenellikle doğrusal modeller doğrusal karar sınırları üretir. Görünüşe göre Rastgele Orman modeli bazı verileri aşacak, XGBoost ve LightGBM modelleri ise daha iyi ve daha genel karar sınırları elde edebilecek. Keras sinir ağının performansı, uygun şekilde eğitilmediği için zayıf.
Birçok kombinasyonda, Keras sinir ağı modeli yalnızca tüm gözlemlerin belirli bir kategoriye ait olduğunu tahmin eder (yine, modelde çok fazla ayarlama yapmadım ve modelin eğitilmesi gereken yalnızca 100 gözlemi var, ancak 40.000 noktayı tahmin etmesi gerekiyor). Yani, tüm arka plan rengini maviye veya kırmızıya boyar ve birçok yanlış sınıflandırma gerçekleştirir. Bazı diyagramlarda sinir ağları mükemmel bir sınıflandırmaya ulaşabilirken, diğer diyagramlarda garip karar sınırları oluşturulmuştur - sinir ağları ilginçtir.
Bu rakamlar üzerinde kısa bir analiz yaparak, basit bir lojistik regresyon modeli kullanarak neredeyse mükemmel bir sınıflandırma elde ettiğimiz görülüyor. Ancak her değişken arasındaki ilişki doğrusal olarak ayrılabilir olduğundan, bu şaşırtıcı değildir. Ama yine de XGBoost ve LightGBM modellerini tercih ediyorum, çünkü daha güvenilir bir karar sınırı elde etmek için amaç işlevlerine düzenlileştirme ekleyerek doğrusal olmayan ilişkilerle başa çıkabilirler. Rastgele orman modeli burada başarısız oldu. Karar sınırları iyi yapılmış gibi görünüyor, ancak aslında bazı bulanık ve keskin kısımlar var.
Ancak elbette, daha fazla değişken ve daha büyük boyutların ortaya çıkmasıyla, bu karar verme sınırları daha karmaşık ve doğrusal olmayan hale gelecektir.
for (i in 1: length (plot_data)) {print (ggplot_lists )}Bu modeli bir Amazon Ubuntu EC2 bulut sunucusunda yazdım ancak bir Windows sisteminde R ile bir blog yazısı derlediğimde bazı sorunlarla karşılaştım. Bu sorunlar temel olarak lightgbm paketinin ve paket sürümünün kurulumundan kaynaklanmaktadır. Aşağıdaki paket sürümünü kullanın (yani, en son paket sürümünü kullanın), kod normal şekilde çalışır.
sessionInfo () ## R version 3.6.1 (2019-07-05) ## Platform: x86_64-w64-mingw32 / x64 (64-bit) ## Altında çalışıyor: Windows 10 x64 (build 17763) #### Matrix ürünler: varsayılan #### locale: ## LC_COLLATE = Spanish_Spain.1252 LC_CTYPE = Spanish_Spain.1252 ## LC_MONETARY = Spanish_Spain.1252 LC_NUMERIC = C ## LC_TIME = Spanish_Spain.1252 #### ekli temel paketler: ## istatistik grafikleri grDevices veri kümesi yöntemlerini kullanır temel #### diğer ekli paketler: ## tidyquant_0.5.7 quantmod_0.4-15 ## TTR_0.23-6 PerformanceAnalytics_1.5.3 ## xts_0.11-2 zoo_1.8-6 ## lubridate_1.7.4 keras_2.2.5.0 ## lightgbm_2.3.2 R6_2.4.1 ## xgboost_0.90.0.1 tidyr_1.0.0 ## stringr_1.4.0 purrr_0.3.2 ## kableExtra_1.1.0.9000 knitr_1.25.4 ## ggplot2_3.2.1 patchwork_1.0.0 # # dplyr_0.8.99.9000 #### bir ad alanı aracılığıyla yüklendi (ve eklenmemiş): ## Rcpp_1.0.3 lattice_0.20-38 class_7.3-15 ## utf8_1.1.4 assertthat_0.2.1 zeallot_0.1.0 ## Digest_0. 6.24 e1071_1.7-2 eval_0.14 ## httr_1.4.1 blogdown_0.15 pillar_1.4.3.9000 ## tfruns_1.4 rlang _0.4.4 lazyeval_0.2.2 ## curl_4.0 rstudioapi_0.10 data.table_1.12.8 ## whisker_0.3-2 Matrix_1.2-17 retiküle_1.14-9001 ## rmarkdown_1.14 lobstr_1.1.1 etiketleme_0.3 ## webshot_0 .5.1 readr_1.3.1 munsell_0.5.0 ## compiler_3.6.1 xfun_0.8 pkgconfig_2.0.3 ## base64enc_0.1-3 tensorflow_2.0.0 htmltools_0.3.6 ## tidyselect_1.0.0 tibble_2.99.99.9014 bookdown_0.13 ## quadprog_1.5 -7 randomForest_4.6-14 fansi_0.4.1 ## viridisLite_0.3.0 crayon_1.3.4 withr_2.1.2 ## rappdirs_0.3.1 grid_3.6.1 Quandl_2.10.0 ## jsonlite_1.6.1 gtable_0.3.0 lifecycle_0.1.0 ## magrittr_1.5 scales_1. 0.0 rlist_0.4.6.1 ## cli_2.0.1 stringi_1.4.3 xml2_1.2.2 ## ellipsis_0.3.0 generics_0.0.2 vctrs_0.2.99.9005 ## tools_3.6.1 glue_1.3.1 hms_0.5.1 ## yaml_2.2.0 colorspace_1.4- 1 yeniden_0.3.4Orjinal başlık:
Bir Seri Makine Öğrenimi Modeli için Karar Sınırı
Orijinal bağlantı:
https://www.kdnuggets.com/2020/03/decision-boundary-series-machine-learning-models.html
Redaksiyon: Lin Yilin
Çevirmen Profili
Zhang Ruonan , UIUC istatistik yüksek lisans mezunu, Güney Kaliforniya medya endüstrisinin veri bilimcisi. Yurt içi ve yurt dışı ticari bankalar, internet, perakende sektörü ve gıda şirketlerinde staj yaptım, farklı alanlardaki veri analizi ve uygulama vakaları ile iletişime geçmeyi seviyorum ve veri bilimi ürün geliştirme konusunda çok heyecanlıyım.
-Bitiş-
Tsinghua-Qingdao Veri Bilimi Enstitüsü'nün resmi WeChat kamu platformunu takip edin " AI Veri Pastası "Ve kız kardeş numarası" Veri Pastası THU "Daha fazla ders avantajı ve kaliteli içerik elde edin.