Subskrypcja JoVE jest wymagana do oglądania tego materiału. Zaloguj się lub rozpocznij bezpłatny okres próbny.

Artykuł metodologiczny

Porównanie skuteczności predykcyjnej trzech systemów oceny stopnia zaawansowania węzłów chłonnych w raku sygnetowym jelita grubego w oparciu o model uczenia maszynowego

1.2K wyświetleń

DOI:

10.3791/67941

18 kwietnia 2025

* These authors contributed equally

W tym artykule

Podsumowanie

To badanie ocenia systemy prognostyczne dla pacjentów z rakiem sygnetowokomórkowym jelita grubego przy użyciu modeli uczenia maszynowego i konkurencyjnych analiz ryzyka. Identyfikuje logarytmiczne szanse dodatnich węzłów chłonnych jako lepszy predyktor w porównaniu z stopniem zaawansowania pN, wykazując wysoką skuteczność predykcyjną i wspomagając podejmowanie decyzji klinicznych dzięki solidnym narzędziom do przewidywania przeżycia.

Streszczenie

Stan węzłów chłonnych jest krytycznym prognostykiem dla pacjentów; jednak prognozowanie raka sygnetowokomórkowego jelita grubego (SRCC) przyciągnęło ograniczoną uwagę. W tym badaniu zbadano zdolność predykcyjną zdolności prognostycznych, logarytmicznych szans dodatnich węzłów chłonnych (LODDS), stosunku węzłów chłonnych (LNR) i stopnia zaawansowania pN u pacjentów z SRCC przy użyciu modeli uczenia maszynowego (Random Forest, XGBoost i Neural Network) wraz z konkurencyjnymi modelami ryzyka. Odpowiednie dane uzyskano z bazy danych Nadzoru, Epidemiologii i Wyników Końcowych (SEER). W przypadku modeli uczenia maszynowego czynniki prognostyczne dla przeżycia specyficznego dla raka (CSS) zostały zidentyfikowane za pomocą jednowymiarowych i wielowymiarowych analiz regresji Coxa, a następnie zastosowano trzy metody uczenia maszynowego - XGBoost, RF i NN - w celu ustalenia optymalnego systemu oceny węzłów chłonnych. W konkurencyjnym modelu ryzyka zastosowano jednoczynnikowe i wielowymiarowe konkurencyjne analizy ryzyka w celu identyfikacji czynników prognostycznych, a także skonstruowano nomogram do przewidywania rokowania pacjentów z SRCC. Obszar pod krzywą charakterystyki operacyjnej odbiornika (AUC-ROC) i krzywe kalibracyjne wykorzystano do oceny wydajności modelu. Do badania włączono łącznie 2 409 pacjentów z SRCC. Aby zweryfikować skuteczność modelu, do walidacji zewnętrznej włączono dodatkową kohortę 15 122 pacjentów z rakiem jelita grubego, z wyłączeniem przypadków SRCC. Zarówno modele uczenia maszynowego, jak i konkurujący ze sobą nomogram ryzyka wykazały się wysoką wydajnością w przewidywaniu wyników przeżycia. W porównaniu z stopniowaniem pN, systemy oceny stopnia zaawansowania LODDS wykazały się lepszymi zdolnościami prognostycznymi. Po dokonaniu oceny modele uczenia maszynowego i konkurujące ze sobą modele ryzyka osiągnęły doskonałą wydajność predykcyjną charakteryzującą się dobrą dyskryminacją, kalibracją i możliwością interpretacji. Nasze odkrycia mogą pomóc pacjentom w podejmowaniu decyzji klinicznych.

Wprowadzenie

Rak jelita grubego (CRC) jest trzecim najczęściej występującym nowotworem złośliwym na świecie1,2,3. Rak sygnetowokomórkowy (SRCC), rzadki podtyp CRC, stanowi około 1% przypadków i charakteryzuje się obfitą wewnątrzkomórkową mucyną wypierającą jądro komórkowe1,2,4. SRCC jest często kojarzona z młodszymi pacjentami, częściej występuje u kobiet i ma zaawansowane stadia nowotworu w momencie rozpoznania. W porównaniu z gruczolakorakiem jelita grubego, SRCC wykazuje gorsze różnicowanie, większe ryzyko odległych przerzutów i 5-letni wskaźnik przeżycia wynoszący tylko 12%-20%5,6. Opracowanie dokładnego i skutecznego modelu prognostycznego dla SRCC ma kluczowe znaczenie dla optymalizacji strategii leczenia i poprawy wyników klinicznych.

To badanie ma na celu skonstruowanie solidnego modelu prognostycznego dla pacjentów z SRCC przy użyciu zaawansowanych metod statystycznych, w tym uczenia maszynowego (ML) i konkurencyjnych modeli ryzyka. Metodologie te mogą uwzględniać złożone relacje w danych klinicznych, oferując zindywidualizowaną ocenę ryzyka i przewyższając tradycyjne metody pod względem dokładności predykcyjnej. Modele uczenia maszynowego, takie jak Random Forest, XGBoost i sieci neuronowe, doskonale sprawdzają się w przetwarzaniu danych wielowymiarowych i identyfikowaniu skomplikowanych wzorców. Badania wykazały, że modele sztucznej inteligencji skutecznie przewidują wyniki przeżycia w raku jelita grubego, podkreślając potencjał ML w zastosowaniach klinicznych7,8. Uzupełniając uczenie maszynowe, konkurencyjne modele ryzyka uwzględniają wiele typów zdarzeń, takich jak śmiertelność specyficzna dla raka w porównaniu z innymi przyczynami zgonu, aby udoskonalić analizę przeżycia. W przeciwieństwie do tradycyjnych metod, takich jak estymator Kaplana-Meiera, konkurencyjne modele ryzyka dokładnie szacują krańcowe prawdopodobieństwo zdarzeń w obecności konkurencyjnych zagrożeń, zapewniając bardziej precyzyjne oceny przeżycia8. Integracja uczenia maszynowego i konkurencyjnej analizy ryzyka zwiększa wydajność predykcyjną, oferując potężną platformę dla spersonalizowanych narzędzi prognostycznych w SRCC9,10,11.

Przerzuty do węzłów chłonnych znacząco wpływają na rokowanie i nawroty u pacjentów z CRC. Podczas gdy ocena N-etapu w klasyfikacji TNM jest krytyczna, nieodpowiednie badanie węzłów chłonnych - zgłaszane w 48%-63% przypadków - może prowadzić do niedoszacowania choroby. Aby temu zaradzić, wprowadzono alternatywne podejścia, takie jak współczynnik węzłów chłonnych (LNR) i logarytm szans dodatnich węzłów chłonnych (LODDS). LNR, stosunek dodatnich węzłów chłonnych (PLN) do całkowitej liczby węzłów chłonnych (TLN), ma mniejszy wpływ na liczbę TLN i służy jako czynnik prognostyczny w CRC. LODDS, logarytmiczny stosunek PLN do ujemnych węzłów chłonnych (NLN), wykazał wyższą zdolność predykcyjną zarówno w SRCC żołądka, jak i raku jelita grubego10,11. Uczenie maszynowe jest coraz częściej stosowane w onkologii, a modele poprawiają stratyfikację ryzyka i prognozy prognostyczne w przypadku różnych nowotworów, w tym raka piersi, prostaty i płuc12,13,14. Jednak jego zastosowanie w SRCC jelita grubego pozostaje ograniczone.

To badanie ma na celu wypełnienie tej luki poprzez integrację LODDS z ML i konkurencyjnymi modelami ryzyka, aby stworzyć kompleksowe narzędzie prognostyczne w celu stworzenia kompleksowego narzędzia prognostycznego. Oceniając wartość prognostyczną, LODDS i wykorzystując zaawansowane techniki predykcyjne, badania te mają na celu usprawnienie procesu podejmowania decyzji klinicznych i poprawę wyników leczenia pacjentów z SRCC.

Dostęp ograniczony. Zaloguj się lub rozpocznij wersję próbną, aby wyświetlić tę treść.

Protokół

To badanie nie odnosi się do etycznego zatwierdzenia i zgody na uczestnictwo. Dane wykorzystane w tym badaniu uzyskano z baz danych. Uwzględniliśmy pacjentów, u których w latach 2004-2015 zdiagnozowano raka sygnetowo-pierścieniowego jelita grubego, a także inne rodzaje raka jelita grubego. Kryteria wykluczenia obejmowały pacjentów, u których czas przeżycia wynosił mniej niż jeden miesiąc, pacjentów z niepełnymi informacjami kliniczno-patologicznymi oraz przypadki, w których przyczyna zgonu była niejasna lub nieokreślona.

1. Akwizycja danych

  1. Pobierz SEER. Oprogramowanie statystyczne 8.4.3 można pobrać ze strony internetowej bazy danych SEER (http://seer.cancer.gov/about/overview.html). Po zalogowaniu się do oprogramowania kliknij Sesja listy spraw > Dane i wybierz bazę danych Incidence SEER Research Plus Data, 17 rejestrów, listopad 2021 Sub (2000-2019).
  2. Kliknij na Selekcja > Edytuj i wybierz {Rasa, Płeć, Rok Dx. Rok diagnozy} = '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015' ORAZ {Miejsce i morfologia. Kod strony ICD-O-3/WHO 2008} = '8490/3'.
  3. Następnie kliknij Tabela i w interfejsie dostępnych zmiennych wybierz Recode Age z pojedynczymi wiekami i 100+, Płeć, Małżeń, Recode miejsca ICD-O-3/WHO 2008, Rozmiar guza CS, Regionalny nodes_examined (1988+), Regionalny nodes_positive(1988+), Pochodna AJCC Stage Group, 6th ed (2004-2015), Pochodna AJCC T, 6th ed (2004-2015), Pochodna AJCC N, 6th ed (2004-2015), Pochodna AJCC M, 6th ed (2004-2015), CEA, Rekodowanie promieniowania, Rekodowanie chemioterapii (tak, nie/unk), klasyfikacja zgonów SEER w zależności od przyczyny, Rekodowanie stanu życiowego (zastosowana granica badania), Miesiące przeżycia, Rok diagnozy.
  4. Na koniec kliknij Wyjście, nazwij dane i kliknij Wykonaj, aby wyprowadzić i zapisać dane. Szczegółowy proces włączania jest pokazany w Rysunek 1.
  5. Pobieranie danych od pacjentów z rakiem jelita grubego, z wyłączeniem przypadków SRCC, w celu późniejszej walidacji zewnętrznej. Kliknij Selekcja > Edytuj i wybierz {Rasa, Płeć, Rok Dx. Rok diagnozy} = '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015' ORAZ {Główny ośrodek - oznaczony} = 'C18-C20'. Powtórz kroki 1.3 i 1.4, aby uzyskać kliniczne informacje patologiczne i wykluczyć próbki z {Site and Morphology. Witryna ponownie koduje ICD-O-3/WHO 2008} = '8490/3' z pobranego pliku.
  6. W celach porównawczych przeanalizuj kilka zmiennych. Klasyfikuj stan węzłów chłonnych, używając zarówno współczynnika węzłów chłonnych (LNR), jak i logarytmu szans na dodatnie węzły chłonne (LODDS).
    1. Zdefiniuj LNR jako stosunek dodatnich węzłów chłonnych (PLN) do całkowitej liczby węzłów chłonnych (TLN). Oblicz wartość LODDS za pomocą wzoru:
      loge(liczba PLN + 0,5) / (liczba ujemnych węzłów chłonnych (NLN) + 0,5)
      gdzie 0,5 zostało dodane, aby zapobiec nieskończonemu wynikowi. Wartości odcięcia dla LNR, LODDS i wielkości guza określono za pomocą oprogramowania X-tile (wersja 3.6.1) w oparciu o metodę minimalnej wartości P.
  7. Otwórz oprogramowanie X-tile, kliknij Plik > Otwórz i wybierz plik danych, aby zaimportować go do oprogramowania. Po załadowaniu danych zmapuj zmienne: Censor odpowiada statusowi przeżycia, Czas przeżycia odpowiada czasowi przeżycia, a marker1 jest zmienną, która ma być analizowana, upewniając się, że dane są poprawnie dopasowane.
  8. Następnie kliknij przycisk Do > Kaplana-Meiera > Marker1, aby przeprowadzić analizę przeżycia Kaplana-Meiera i wygenerować krzywą przeżycia. Na podstawie separacji krzywych przeżycia Kaplana-Meiera, istotności statystycznej (np. wartości p) i istotności klinicznej określ optymalną wartość odcięcia, a na koniec zapisz lub wyeksportuj wyniki analizy.
    1. Podziel LNR na trzy grupy: LNR 1 (≤0,16), LNR 2 (0,16 - 0,78) i LNR 3 (≥ 0,78). Podziel pacjentów na trzy grupy na podstawie LODDS: LODDS 1 (≤ -1,44), LODDS 2 (-1,44 - 0,86) i LODDS 3 (≥ 0,86).
    2. Podziel rozmiar guza na trzy kategorie: ≤ 3,5 cm, 3,5 - 5,5 cm i ≥ 5,5 cm. Przelicz wiek ze zmiennej ciągłej na kategoryczną. Kategoryzuj wiek pacjentów w momencie wstępnej diagnozy jako ≥60 lat i <60 lat. Klasyfikuj lokalizację guza na podstawie rozmieszczenia guzów raka sygnetowokomórkowego (SRCC) jako prawej okrężnicy, lewej okrężnicy i odbytnicy. Prawa okrężnica obejmuje jelito ślepe, okrężnicę wstępującą, zgięcie wątroby i okrężnicę poprzeczną, podczas gdy lewa okrężnica obejmuje zgięcie śledziony, okrężnicę zstępującą, esicę i połączenie odbytniczo-esicze.
  9. W tym badaniu losowo przypisz łącznie 2409 kwalifikujących się danych pacjentów z SRCC do kohorty treningowej (N = 1686) i kohorty walidacyjnej (N = 723) w stosunku 7:3. Użyj poniższego kodu do losowego podziału i pozyskuj data.csv z bazy danych SEER. Pliki wygenerowane po losowym podziale zostaną wykorzystane do dalszej analizy.
    biblioteka(daszek)
    Dane <- read.csv("data.csv")
    set.seed(123)
    train_indices <- createDataPartition(data$zmienna, p = 0.7, list = FALSE)
    train_data <- data[train_indices, ]
    test_data <- data[-train_indices, ]
    write.csv(train_data, "traindata.csv", row.names = FALSE)
    write.csv(test_data, "testdata.csv", row.names = FAŁSZ)

2. Rozwój i weryfikacja modeli ML

  1. Pobierz oprogramowanie RStudio (2024.04.2+764) i R (4.4.1). Otwórz program RStudio, aby uruchomić oprogramowanie języka R. Kliknij pozycję Nowy plik i wybierz pozycję Skrypt języka R, aby utworzyć nowy interfejs programowania języka R. Wprowadź odpowiedni kod w edytorze kodu i kliknij Uruchom, aby wykonać kod.
  2. Użyj poniższego kodu, aby przesiewać zmienne zawarte w modelach uczenia maszynowego za pomocą analizy regresji Coxa. Ponadto zbadaj wpływ LODDS, LNR i oceny stopnia zaawansowania pN na przeżycie specyficzne dla raka (CSS) u pacjentów z SRCC. traindata.csv to dane uzyskane z bazy danych SEER.
    biblioteka("przetrwanie")
    library("survminer")
    biblioteka("rms")
    biblioteka("dplyr")
    Dane <- read.csv("traindata.csv")
    data$time=as.numeric(data$time)
    data$status=as.numeric(data$status)
    zmienne <- c("Płeć", "Wiek", "Rasa", "Małżeński", "Etap", "T", "N", "M","Tumor_size", "LNR", "LODDS", "CEA", "Radioterapia", "Chemioterapia", "Miejsce")
    Data <- dane %>%
    mutate(across(all_of(variables), as.factor))
    cox=coxph(Surv(czas, status) ~ data$T, dane = dane)
    cox$współczynniki
    pval=anova(cox)$Pr[2]
    clean_data=dane[,c(1:12, 14:18)]
    get_coxVariable=function(your_data,index){cox_list=c() k=1
    for (i in 1:index) {mod=coxph(Surv(time, status) ~ your_data[,i],data=your_data) pval=anova(mod)$Pr[2] print(pval) print(colnames(your_data)[i]) if (pval<0.05) {cox_list[k]=colnames(your_data)[i] k=k+1}}return(cox_list)}
    variable_select=get_coxVariable(clean_data,15)
    for(i w 1:15){print(variable_select[i])}
    for (var in variable_select) {formula <- as.formula(paste("Surv(time, status) ~", var))cox_model <- coxph(formula, data = data) print(summary(cox_model)))
    ggforest(sternik)
    zmienne <- c("Płeć", "Wiek", "Rasa", "Małżeński", "Etap", "T", "N", "M", "Tumor_size", "LNR", "LODDS", "Chemioterapia")
    Data <- dane %>%
    mutate(across(all_of(variables), as.factor))
    cox=coxph(Surv(czas, status) ~ Płeć+Wiek+Rasa+Małżeński+T+N+M+Tumor_size+LNR+
    LODDS+Chemioterapia, dane = dane)
    ggforest(cox,dane = dane)
    ggplot_forest <- ggforest(cox, dane = dane)
  3. Użyj poniższego kodu, aby porównać możliwości przewidywania prognostycznego trzech systemów LN (LODDS, LNR i inscenizacja pN) w kohortach trenowania, walidacji i walidacji zewnętrznej.
    biblioteka(rms)
    biblioteka(przetrwanie)
    biblioteka(survminer)
    biblioteka(ryzykoRegresja)
    biblioteka(gt)
    train_data <- read.csv("train_data123.csv")
    validation_data <- read.csv("test_data123.csv")
    dd <- datadist(train_data)
    opcje(rozkład.danych = "dd")
    model_LNR <- cph(Surv(czas, status) ~ LNR, dane = train_data, x = PRAWDA, y = PRAWDA)
    model_LODDS <- cph(Surv(czas, status) ~ LODDS, dane = train_data, x = PRAWDA, y = PRAWDA)
    model_pN <- cph(Surv(czas, status) ~ N, dane = train_data, x = PRAWDA, y = PRAWDA)
    calculate_performance <- function(model, data) {pred <- predict(model, newdata = dane) c_index_result <- concordance(Surv(data$time, data$status) ~ pred) c_index <- c_index_result$konkordancja aic <- AIC(model) bic <- BIC(model) return(c(C_index = round(c_index, 3), AIC = round(aic, 2), BIC = round(bic, 2)))}
    calculate_performance <- funkcja(model, dane) {pred <- predict(model, newdata = data, type = "lp") concordance_result <- concordancefit(Surv(data$time, data$status), x = pred) c_index <- concordance_result$konkordancja ci_lower <- c_index - 1.96 * sqrt(concordance_result$var) ci_upper <- c_index + 1.96 * sqrt(concordance_result$var) aic <- AIC(model) bic <- BIC(model) return(c(C_Index = round(c_index, 3), CI_Lower = round(ci_lower, 3), CI_Upper = round(ci_upper, 3), AIC = round(aic, 2), BIC = round(bic, 2)))}
    train_LNR <- calculate_performance(model_LNR, train_data)
    train_LODDS <- calculate_performance(model_LODDS, train_data)
    train_pN <- calculate_performance(model_pN, train_data)
    model_LNR_val <- cph(Surv(czas, status) ~ LNR, dane = validation_data, x = PRAWDA, y = PRAWDA)
    model_LODDS_val <- cph(Surv(czas, status) ~ LODDS, dane = validation_data, x = PRAWDA, y = PRAWDA)
    model_pN_val <- cph(Surv(czas, status) ~ N, dane = validation_data, x = PRAWDA, y = PRAWDA)
    val_LNR <- calculate_performance(model_LNR_val, validation_data)
    val_LODDS <- calculate_performance(model_LODDS_val, validation_data)
    val_pN <- calculate_performance(model_pN_val, validation_data)
    wyniki <- data.frame(Zmienna = c("LNR", "LODDS", "pN"), Training_C_Index = c(paste(train_LNR["C_Index"], "(", train_LNR["CI_Lower"], ", ", train_LNR["CI_Upper"], ")", sep = ""), paste(train_LODDS["C_Index"], "(", train_LODDS["CI_Lower"], ", ", train_LODDS["CI_Upper"], ")", sep = ""), wklej(train_pN["C_Index"], "(", train_pN["CI_Lower"], ", ", train_pN["CI_Upper"], ")", sep = "")"), Training_AIC = c(train_LNR["AIC"], train_LODDS["AIC"], train_pN["AIC"]), Training_BIC = c(train_LNR["BIC"], train_LODDS["BIC"], train_pN["BIC"]), Validation_C_Index = c(wklej(val_LNR["C_Index"], "(", val_LNR["CI_Lower"], ", ", val_LNR["CI_Upper"], ")", sep = ""), wklej(val_LODDS["C_Index"], "(", val_LODDS["CI_Lower"], ", ", val_LODDS["CI_Upper"], ")", sep = ""), wklej(val_pN["C_Index"], "(", val_pN["CI_Lower"], ", ", val_pN["CI_Upper"], ")", sep = "")), Validation_AIC = c(val_LNR["AIC"], val_LODDS["AIC"], val_pN["AIC"]), Validation_BIC = c(val_LNR["BIC"], val_LODDS["BIC"], val_pN["BIC"]))
    results_table <- gt(wyniki) %>%
    tab_header(title = "Wydajność predykcyjna trzech węzłowych systemów oceny węzłów chłonnych") %>%
    cols_label(Zmienna = "Zmienna",Training_C_Index = "Indeks C (95% CI) (Szkolenie)", Training_AIC = "AIC (Szkolenie)", Training_BIC = "BIC (Szkolenie)", Validation_C_Index = "Indeks C (95% CI) (Walidacja)", Validation_AIC = "AIC (Walidacja)", Validation_BIC = "BIC (Walidacja)")
    write.csv(wyniki, "prediction_performance.csv", row.names = FAŁSZ)
  4. Użyj poniższego kodu, aby zbudować model XGBoost i wygenerować wykresy słupkowe względnej ważności zmiennych, aby w ten sposób porównać znaczenie trzech systemów LN. Podobnie wygeneruj krzywe ROC i krzywe kalibracyjne. Dane pochodzą z bazy danych SEER.
    biblioteka(xgboost)
    biblioteka(daszek)
    biblioteka(pROC)
    train_data <- read.csv("train_data.csv")
    test_data <- read.csv("test_data.csv")
    train_matrix <- xgb. DMatrix(data = as.matrix(train_data[, c('Wiek', 'T', 'N', 'M', 'LODDS', 'Chemioterapia')]), label = train_data$status)
    test_matrix <- xgb. DMatrix(data = as.matrix(test_data[, c('Wiek', 'T', 'N', 'M', 'LODDS', 'Chemioterapia')]), label = test_data$status)
    Params <- list(booster = "gbtree", objective = "binary:logistic", eval_metric = "AUC", ETA = 0,1, max_depth = 6, podpróbka = 0,8, colsample_bytree = 0,8)
    xgb_model <- xgb.train(params = parametry, dane = train_matrix, nrounds = 100, watchlist= list(train = train_matrix), verbose = 1)
    pred_probs <- predict(xgb_model, newdata = test_matrix)
    pred_labels <- ifelse(pred_probs > 0.5, 1, 0)
    conf_matrix <- zamieszanieMatrix(as.factor(pred_labels), as.factor(test_data$status))
    roc_curve <- roc(test_data$status, pred_probs)
    auc_value <- AUC(roc_curve)
    ci_auc <- ci.auc(roc_curve)
    czułość <- conf_matrix$byClass["Czułość"]
    specyficzność <- conf_matrix$byClass["Specyficzność"]
    dokładność <- conf_matrix$overall["Dokładność"]
    ppv <- conf_matrix$byClass["Wartość Pred Pos"]
    npv <- conf_matrix$byClass["Wartość neg pred"]
    result_table <- data.frame(Model = "XGBoost", AUC = sprintf("%.3f (%.3f-%.3f)", auc_value, ci_auc[1], ci_auc[3]), Czułość = sprintf("%.3f", czułość), Specyficzność = sprintf("%.3f", specyficzność), Dokładność = sprintf("%.3f", dokładność), PPV = sprintf("%.3f", ppv), NPV = sprintf("%.3f", npv))
    write.csv(result_table, "xgboost_model_performance.csv", row.names = FALSE)
    roc_df <- data.frame(FPR = 1 - roc_curve$specyfiki, TPR = roc_curve$czułości)
    roc_plot <- ggplot(roc_df, aes(x = FPR, y = TPR)) +geom_line(kolor = "stalowy", rozmiar = 1,2) + geom_abline(punkt przecięcia = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "szary") + adnotacja("tekst", x = 0,9, y = 0,2, etykieta = paste("AUC =", round(auc_value, 3)), rozmiar = 5, kolor = "") + labs(tytuł = "Krzywa ROC dla modelu XGBoost", x = "Odsetek wyników fałszywie dodatnich", y = "Odsetek wyników prawdziwie dodatnich") + theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 1))
    calibration_data <- data.frame(Status = as.factor(test_data$status), pred_probs = pred_probs)
    calib_model <- kalibracja(Status ~ pred_probs, dane = calibration_data, klasa = "1", cięcia = 5)
    ggplot(calib_model$data, aes(x = punkt środkowy, y = procent)) + geom_line(kolor = "stalowy", rozmiar = 1) + geom_point(kolor = "czerwony", rozmiar = 2) + geom_abline(punkt przecięcia = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "") +labs(tytuł = "Krzywa kalibracji dla modelu XGBoost", x = "Przewidywane prawdopodobieństwo", y = "Obserwowana proporcja") + theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 0,5))
  5. Użyj poniższego kodu, aby zbudować model RF i wygenerować wykresy słupkowe względnej ważności zmiennych, porównując w ten sposób znaczenie trzech systemów LN. Podobnie wygeneruj krzywe ROC i krzywe kalibracyjne. Dane są uzyskiwane z bazy danych SEER.library(randomForest)
    biblioteka(dplyr)
    biblioteka(ggplot2)
    biblioteka(pROC)
    biblioteka(daszek)
    biblioteka(rms)
    Pociąg składowy <- read.csv("train_data.csv")
    testowane <- read.csv("test_data.csv")
    trainset$status=czynnik(trainset$status)
    zmienne1 <- c("Wiek", "T", "N", "M", "LODDS", "Chemioterapia")
    trainset <- trainset %>%
    mutate(across(all_of(variables1), as.numeric))
    tested$status=czynnik(testowany$status)
    testowane < - testowane %>%
    mutate(across(all_of(variables1), as.numeric))
    RF=randomForest(trainset$status ~ Wiek + T + N + M + LODDS + Chemioterapia, data=trainset,ntree=100,importance=TRUE,proximity=TRUE)
    imp=ważność(RF)
    varImpPlot(RF)
    impvar=nazwy wierszy(chochlik)[porządek(imp[,4],malejący = PRAWDA)]
    importance_df <- as.data.frame(imp)
    importance_df$Zmienne <- nazwy wierszy(importance_df)
    importance_plot <- ggplot(importance_df, aes(x = reorder(Zmienne, ŚredniaZmniejszDokładności), y = ŚredniaZmniejszAccuracy)) +geom_bar(stat = "tożsamość", fill = "stalowy") +coord_flip() + labs(title = "Znaczenie zmiennej", x = "Zmienne", y = "Średnia dokładność zmniejszenia") + theme_minimal()
    pred_probs <- predict(RF, zestaw testowy, typ = "prob")[,2]
    roc_obj <- roc(testset$status, pred_probs)
    auc_value <- AUC(roc_obj)
    roc_plot <- ggplot() +geom_line(aes(x = 1 - roc_obj$specyfiki, y = roc_obj$czułości), kolor = "stalowyniebieski", rozmiar = 1,2) +geom_abline(przecięcie = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "szary") + adnotacja("tekst", x = 0,8, y = 0,2, etykieta = paste("AUC =", okrągł(auc_value, 3)), kolor = "", rozmiar = 5, hjust = 0) + labs(title = "Krzywa ROC dla losowego modelu lasu", x = "Wskaźnik wyników fałszywie dodatnich", y = "Wskaźnik wyników prawdziwie dodatnich") +theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 1))
    calibration_data <- data.frame(pred_probs = pred_probs, status = testowany$status)
    calib_model <- kalibracja(stan ~ pred_probs, dane = calibration_data, klasa = "1", cięcia = 5)
    calib_df <- as.data.frame(calib_model[["data"]])
    calib_df$mid <- calib_df$midpoint
    calib_df$Procent <- calib_df$Procent
    calibration_plot <- ggplot(calib_df, aes(x = średni, y = procent)) + geom_line(kolor = "stalowy", rozmiar = 1,2) + geom_point(kolor = "stalowy", rozmiar = 3) + geom_abline(punkt przecięcia = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "", rozmiar = 0,8) + labs(tytuł = "krzywa kalibracyjna dla lasu losowego", x = "Przewidywane prawdopodobieństwo", y = "Rzeczywiste prawdopodobieństwo") + theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 1), plot.title = element_text(hjust = -0,05, vjust = -1,5, twarz = "pogrubienie", rozmiar = 12) )
    rf_probs <- predict(RF, newdata=testowany, type="prob")[, 2]
    rf_auc <- roc(tested$status, rf_probs)
    auc_value <- AUC(rf_auc)
    ci_auc <- ci.auc(rf_auc)
    rf_predictions <- predict(RF, newdata=testowane)
    conf_matrix <- zamieszanieMatrix(rf_predictions, tested$status)
    czułość <- conf_matrix$byClass["Czułość"]
    specyficzność <- conf_matrix$byClass["Specyficzność"]
    dokładność <- conf_matrix$overall["Dokładność"]
    ppv <- conf_matrix$byClass["Wartość Pred Pos"]
    npv <- conf_matrix$byClass["Wartość neg pred"]
    result_table <- data.frame(Model = "RF", AUC = sprintf("%.3f (%.3f-%.3f)", auc_value, ci_auc[1], ci_auc[3]), Czułość = sprintf("%.3f", czułość), Specyficzność = sprintf("%.3f", specyficzność), Dokładność = sprintf("%.3f", dokładność), PPV = sprintf("%.3f", ppv), NPV = sprintf("%.3f", npv))
    write.csv(result_table, "RF_model_performance.csv", row.names = FAŁSZ)
  6. Poniższy kod służy do budowania modelu NN i generowania wykresów słupkowych względnej ważności zmiennych, porównując w ten sposób ważność trzech układów LN. Podobnie wygeneruj krzywe ROC i krzywe kalibracyjne. Dane są pozyskiwane z bazy danych SEER.library(nnet)
    biblioteka(daszek)
    biblioteka(pROC)
    biblioteka(ggplot2)
    train_data <- read.csv("train_data.csv")
    test_data <- read.csv("test_data.csv")
    train_data$status <- as.factor(train_data$status)
    test_data$status <- as.factor(test_data$status)
    cechy <- c("Wiek", "T", "N", "M", "LODDS", "Chemioterapia")
    x_train <- train_data[, funkcje]
    y_train <- train_data$status
    x_test <- test_data[, funkcje]
    y_test <- test_data$status
    nn_model <- nnet(status ~ Wiek + T + N + M + LODDS + Chemioterapia, dane = train_data, rozmiar = 5, rozpad = 0,01, maxit = 200)
    pred_probs <- predict(nn_model, newdata = x_test, type = "surowy")
    pred_labels <- ifelse(pred_probs > 0.5, 1, 0)
    roc_curve <- roc(as.numeric(y_test), pred_probs)
    auc_value <- AUC(roc_curve)
    auc_ci <- ci.auc(roc_curve)
    auc_text <- paste0(round(auc_value, 3), " (", round(auc_ci[1], 3), "-", round(auc_ci[3], 3), ")")
    conf_matrix <- zamieszanieMatrix(as.factor(pred_labels), y_test)
    dokładność <- conf_matrix$overall["Dokładność"]
    czułość <- conf_matrix$byClass["Czułość"]
    specyficzność <- conf_matrix$byClass["Specyficzność"]
    ppv <- conf_matrix$byClass["Wartość Pred Pos"]
    npv <- conf_matrix$byClass["Wartość neg pred"]
    performance_table <- data.frame(Metryka = c("AUC (95% CI)", "Dokładność", "Czułość", "Specyficzność", "PPV", "NPV"),Wartość = c(auc_text, round(dokładność, 3), round(czułość, 3), round(specyficzność, 3), round(ppv, 3), round(npv, 3))))
    write.csv(performance_table, "NN_performance_table.csv", row.names = FALSE)
    roc_curve <- roc(y_test, pred_probs)
    auc_value <- AUC(roc_curve)
    roc_plot <- ggplot() + geom_line(aes(x = 1 - roc_curve$specyfiki, y = roc_curve$czułości), kolor = "stalowyniebieski", rozmiar = 1,2) +geom_abline(przecięcie = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "szary") + adnotacja("tekst", x = 0,8, y = 0,2, etykieta = paste("AUC =", round(auc_value, 3)), kolor = "", rozmiar = 5, hjust = 0) + labs(tytuł = "Krzywa ROC dla modelu sieci neuronowej", x = "Wskaźnik wyników fałszywie dodatnich", y = "Wskaźnik wyników prawdziwie dodatnich") + theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 1))
    calibration_data <- data.frame(pred_probs = pred_probs, status = as.numeric(y_test) - 1)
    calibration_data$pred_probs <- as.numeric(calibration_data$pred_probs)
    calibration_data$calibration_bin <- cut(calibration_data$pred_probs, breaks = seq(0, 1, by = 0.2), include.least = TRUE)
    calibration_summary <- agregacja(status ~ calibration_bin, dane = calibration_data, FUN = średnia)
    calibration_summary$pred_mean <- aggregate(pred_probs ~ calibration_bin, data = calibration_data, FUN = średnia)$pred_probs
    calibration_plot <- ggplot(calibration_summary, aes(x = pred_mean, y = status)) + geom_line(kolor = "stalowy", rozmiar = 1,2) + geom_point(kolor = "czerwony", rozmiar = 3) + geom_abline(punkt przecięcia = 0, nachylenie = 1, rodzaj linii = "przerywany", kolor = "", rozmiar = 0,8) + labs(tytuł = "krzywa kalibracji sieci neuronowej", x = "Przewidywane prawdopodobieństwo", y = "Rzeczywiste prawdopodobieństwo") + theme_minimal() + theme(panel.border = element_rect(kolor = "", wypełnienie = NA, rozmiar = 1))
    nn_var_importance <- varImp(nn_model)
    importance_df <- data.frame(Cecha = nazwy wierszy(nn_var_importance), Ważność = nn_var_importance$Ogółem )
    importance_plot <- ggplot(importance_df, aes(x = reorder(Cecha, Ważność), y = Ważność)) + geom_bar(stat = "tożsamość", fill = "stalowy") + coord_flip() + labs(tytuł = "Zmienna ważność sieci neuronowej", x = "Cechy", y = "Ważność") + theme_minimal()

3. Opracowanie i weryfikacja konkurencyjnego modelu ryzyka

  1. Użyj poniższego kodu, aby przeprowadzić analizę jednowymiarową i wykreślić krzywą skumulowanej funkcji częstości występowania (CIF). data.csv to dane pozyskane z bazy danych SEER. Sposób zapisywania kolejnych obrazów będzie taki sam jak w tym kroku. Zastąp pole Site w kodzie jeden po drugim innymi czynnikami, aby przeprowadzić analizę jednowymiarową dla wszystkich czynników.
    biblioteka(tidycmprsk)
    biblioteka(gtsummary)
    biblioteka(ggplot2)
    biblioteka(ggsurvfit)
    biblioteka(ggprism)
    aa <- read.csv("data.csv")
    cif2 <- tidycmprsk::cuminc(Surv(czas, Status1) ~Strona, dane = aa)
    tidy(CIF2,razy = C(12,24,36,48,60))
    tbl_cuminc(cif2, razy =c(12,24,36,48,60), wyniki = c("CSS", "OSS"),estimate_fun = NULL, label_header = "**{czas/12}-rok cuminc**") %>%
    add_p() %>%
    add_n(lokalizacja = "poziom")
    cuminc_plot <- ggcuminc(cif2, wynik = c("CSS", "OSS"), rozmiar = 1,5) + labs(x = "czas") +add_quantile(y_value = 0,20, rozmiar = 1) + scale_x_continuous(przerwy = seq(0, 84, by = 12), limity = c(0, 84)) +scale_y_continuous(etykieta = scales::p ercent, breaks = seq(0, 1, by = 0,2), limity = c(0, 1)) + theme_prism() + theme(legend.position = c(0,2, 0.8), panel.grid = element_blank(),panel.grid.major.y = element_line(kolor = "szary80")) + theme(legend.spacing.x = jednostka(0.1, "cm"), legend.spacing.y = jednostka(0.01, "cm")) + theme(axis.ticks.length.x = jednostka(-0.2, "cm"), axis.ticks.x = element_line(kolor = "", rozmiar = 1, koniec linii = 1)) + theme(axis.ticks.length.y = jednostka(-0.2, "cm"), axis.ticks.y = element_line(kolor = "", rozmiar = 1, koniec linii = 1))
  2. Poniższy kod służy do przeprowadzania analizy i wizualizacji wielowymiarowej. data1.csv pochodzi z wyników poprzedniego kodu. Po uruchomieniu kodu kliknij Eksportuj, następnie kliknij Zapisz jako PDF, a na koniec kliknij Zapisz, aby zapisać obraz.
    biblioteka(tidycmprsk)
    biblioteka(gtsummary)
    aa <-read.csv('data1.csv')
    for (i w nazwach(aa)[c(1:16, 19)]){aa[,i] <- as.factor(aa[,i])}
    mul1 table2 <- mul1 %>%
    gtsummary::tbl_regression(wykładnik = PRAWDA) %>%
    add_n(lokalizacja = "poziom"); table2
    table_df <- as_tibble(tabela2)
    Tab <- Tabela2$table_body
    tab1 <- tab[,c(12,19,20,22:29)]
  3. Użyj poniższego kodu, aby wykreślić nomogram, krzywą ROC i krzywą kalibracyjną. Po wytrenowaniu modelu przy użyciu danych z kohorty szkoleniowej użyj danych kohort walidacji i zewnętrznej walidacji, aby zweryfikować model.library(QHScrnomo). Zewnętrzne dane kohortowe składają się z próbek raka jelita grubego innego niż rak pierścieniowo-komórkowy, które zostały wybrane w kroku 1.4.
    biblioteka(rms)
    biblioteka(timeROC)
    biblioteka(przetrwanie)
    aa <-read.csv('data3.csv')
    for (i w nazwach(aa)[c(1:16, 19)]){aa[,i] <- as.factor(aa[,i])}
    dd <- ROZKŁAD.DANYCH(aa)
    opcje(rozkład.danych = "dd")
    mul <- cph(Surv(czas, Status1 == 1) ~ T + N + M + LODDS + Lokalizacja, dane = aa, x = PRAWDA, y = PRAWDA, surv = PRAWDA)
    m3 <- crr.fit(mul, kod awarii = 1, kod cen = 0)
    nomo <-Newlabels(fit = m3, labels =c(T="T", N= "N", M = "M", LODDS = "LODDS", Site = "Site"))
    nomo c("N0","N1","N2"),M=c("M0","M1"),LODDS=c
    ("LODDS1","LODDS2","LODDS3"),Site=
    c("RSC","LSC","Odbyt")))
    nomogram.crr(fit =nomo , lp = F, xfrac = 0.3, fun.at =seq(from=0, to=1, by= 0.1) , failtime =c(12,36,60), funlabel = c("1-roczna skumulowana częstość występowania CSS","3-letnia skumulowana częstość występowania CSS","5-letnia skumulowana częstość występowania CSS"))
    time_points <- c(12, 36, 60)
    pred_risks_list <- lapply(time_points, function(time_point) {predict(m3, newdata = aa, type = "ryzyko", time = time_point)})
    pred_risks_df <- data.frame(do.call(cbind, pred_risks_list))
    colnames(pred_risks_df) <- paste("risk_at", time_points, "miesiące", sep = "_")
    roc_1year <- timeROC(T = aa$time, delta = ifelse(aa$Status1 == "CSS", 1, 0), marker = pred_risks_df$risk_at_12_months, cause = 1, times = 12, iid = TRUE)
    roc_3year <- timeROC(T = aa$time, delta = ifelse(aa$Status1 == "CSS", 1, 0), marker = pred_risks_df$risk_at_36_months, cause = 1, times = 36, iid = TRUE)
    roc_5year <- timeROC(T = aa$time, delta = ifelse(aa$Status1 == "CSS", 1, 0), marker = pred_risks_df$risk_at_60_months, cause = 1,times = 60, iid = TRUE)
    legend("prawy dolny róg",legenda = c("1 rok CSS", "3 rok CSS", "5 lat CSS"), col = c("#BF1D2D", "#262626", "#397FC7"), lwd = 2)
    sas.cmprsk(m3;czas = 36)
    set.seed(123)
    aa$pro <- tenf.crr(m3,czas = 36)
    cindex(prob = aa$pro, fstatus = aa$Status1, ftime = aa$time, type = "crr", failcode = 1, cencode = 0, tol = 1e-20)
    groupci(x=aa$pro, ftime = aa$time, fstatus = aa$Status1, failcode = 1, cencode = 0, ci = TRUE, g = 5, m = 1000, u = 36, xlab = "Przewidywane prawdopodobieństwo", ylab = "Rzeczywiste prawdopodobieństwo", lty=1, lwd=2, col="#262626",xlim=c(0,1.0), ylim=c(0,1.0), add =PRAWDA)

Dostęp ograniczony. Zaloguj się lub rozpocznij wersję próbną, aby wyświetlić tę treść.

Wyniki

Charakterystyka pacjentów
Badanie to skupiło się na pacjentach z diagnozą SRCC jelita grubego, wykorzystując dane z bazy SEER z lat 2004–2015. Kryteria wykluczenia obejmowały pacjentów z czasem przeżycia krótszym niż jeden miesiąc, osoby z niekompletnymi informacjami kliniczno-patologicznymi oraz przypadki, w których przyczyna zgonu była niejasna lub nieokreślona. Łącznie 2409 pacjentów z SRCC jelita grubego, którzy spełnili kryteria włączenia, zostało losowo podzielonych na kohortę treningową (N = 1...

Dostęp ograniczony. Zaloguj się lub rozpocznij wersję próbną, aby wyświetlić tę treść.

Dyskusja

Rak jelita grubego (CRC) SRCC jest rzadkim i szczególnym podtypem raka jelita grubego o złym rokowaniu. Dlatego należy zwrócić większą uwagę na rokowanie pacjentów z SRCC. Dokładne przewidywanie przeżycia pacjentów z SRCC ma kluczowe znaczenie dla określenia ich rokowania i podejmowania zindywidualizowanych decyzji dotyczących leczenia. W tym badaniu zbadaliśmy związek między cechami klinicznymi a rokowaniem u pacjentów z SRCC i zidentyfikowaliśmy optymalny system oceny stopnia zaawansowania LN dla pacjentów z SRCC na po...

Dostęp ograniczony. Zaloguj się lub rozpocznij wersję próbną, aby wyświetlić tę treść.

Oświadczenia

Autorzy nie mają do ujawnienia żadnych finansowych konfliktów interesów.

Materiały

Lista materiałów użytych w tym artykule
NazwaFirmaNumer katalogowyKomentarze
Baza danych SEERKrajowy instytut onkologiczny w oprogramowaniu NIH
X-tileYale school of medicine
R-studioPosit

Bibliografia

  1. Siegel, R. L., Giaquinto, A. N., Jemal, A. Cancer statistics, 2024. CA Cancer J Clin. 74 (1), 12-49 (2024).
  2. Korphaisarn, K., et al. Signet ring cell colorectal cancer: Genomic insights into a rare subpopulation of colorectal adenocarcinoma. Br J Cancer. 121 (6), 505-510 (2019).
  3. Willauer, A. N., et al. Clinical and molecular characterization of early-onset colorectal cancer. Cancer. 125 (12), 2002-2010 (2019).
  4. Watanabe, A., et al. A case of primary colonic signet ring cell carcinoma in a young man which preoperatively mimicked Phlebosclerotic colitis. Acta Med Okayama. 73 (4), 361-365 (2019).
  5. Kim, H., Kim, B. H., Lee, D., Shin, E. Genomic alterations in signet ring and mucinous patterned colorectal carcinoma. Pathol Res Pract. 215 (10), 152566(2019).
  6. Deng, X., et al. Neoadjuvant radiotherapy versus surgery alone for stage II/III mid-low rectal cancer with or without high-risk factors: A prospective multicenter stratified randomized trial. Ann Surg. 272 (6), 1060-1069 (2020).
  7. Buk Cardoso, L., et al. Machine learning for predicting survival of colorectal cancer patients. Sci Rep. 13 (1), 8874(2023).
  8. Monterrubio-Gómez, K., Constantine-Cooke, N., Vallejos, C. A. A review on statistical and machine learning competing risks methods. Biom J. 66 (2), e2300060(2024).
  9. Kim, H. J., Choi, G. S. Clinical implications of lymph node metastasis in colorectal cancer: Current status and future perspectives. Ann Coloproctol. 35 (3), 109-117 (2019).
  10. Xu, T., et al. Log odds of positive lymph nodes is an excellent prognostic factor for patients with rectal cancer after neoadjuvant chemoradiotherapy. Ann Transl Med. 9 (8), 637(2021).
  11. Chen, Y. R., et al. Prognostic performance of different lymph node classification systems in young gastric cancer. J Gastrointest Oncol. 12 (4), 285-1300 (2021).
  12. Bouvier, A. M., et al. How many nodes must be examined to accurately stage gastric carcinomas? Results from a population based study. Cancer. 94 (11), 2862-2866 (2002).
  13. Coburn, N. G., Swallow, C. J., Kiss, A., Law, C. Significant regional variation in adequacy of lymph node assessment and survival in gastric cancer. Cancer. 107 (9), 2143-2151 (2006).
  14. Li Destri, G., Di Carlo, I., Scilletta, R., Scilletta, B., Puleo, S. Colorectal cancer and lymph nodes: the obsession with the number 12. World J Gastroenterol. 20 (8), 1951-1960 (2014).
  15. Dinaux, A. M., et al. Outcomes of persistent lymph node involvement after neoadjuvant therapy for stage III rectal cancer. Surgery. 163 (4), 784-788 (2018).
  16. Sun, Y., Zhang, Y., Huang, Z., Chi, P. Prognostic implication of negative lymph node count in ypN+ rectal cancer after neoadjuvant chemoradiotherapy and construction of a prediction nomogram. J Gastrointest Surg. 23 (5), 1006-1014 (2019).
  17. Xu, Z., Jing, J., Ma, G. Development and validation of prognostic nomogram based on log odds of positive lymph nodes for patients with gastric signet ring cell carcinoma. Chin J Cancer Res. 32 (6), 778-793 (2020).
  18. Scarinci, A., et al. The impact of log odds of positive lymph nodes (LODDS) in colon and rectal cancer patient stratification: a single-center analysis of 323 patients. Updates Surg. 70 (1), 23-31 (2018).
  19. Nitsche, U., et al. Prognosis of mucinous and signet-ring cell colorectal cancer in a population-based cohort. J Cancer Res Clin Oncol. 142 (11), 2357-2366 (2016).
  20. Kang, H., O'Connell, J. B., Maggard, M. A., Sack, J., Ko, C. Y. A 10-year outcomes evaluation of mucinous and signet-ring cell carcinoma of the colon and rectum. Dis Colon Rectum. 48 (6), 1161-1168 (2005).
  21. Sung, C. O., et al. Clinical significance of signet ring cells in colorectal mucinous adenocarcinoma. Mod Pathol. 21 (12), 1533-1541 (2008).
  22. Alvi, M. A., et al. Molecular profiling of signet ring cell colorectal cancer provides a strong rationale for genomic targeted and immune checkpoint inhibitor therapies. Br J Cancer. 117 (2), 203-209 (2017).
  23. Brownlee, S., et al. Evidence for overuse of medical services around the world. Lancet. 390 (10090), 156-168 (2017).

Dostęp ograniczony. Zaloguj się lub rozpocznij wersję próbną, aby wyświetlić tę treść.

Przedruki i uprawnienia

Tagi

Modele uczenia maszynowegoprzewidywanie przeżywalności w rakuklasyfikacja LODDSstos węzłów chłonnychRandom Forestmodel XGBoostmodel sieci neuronowejmodel ryzyka konkurencyjnego