[{"data":1,"prerenderedAt":1116},["ShallowReactive",2],{"lang-switch-post-\u002Fplaylists\u002Fmachine-learning-specialization\u002Fscikit-learn-pitfalls":3,"post-pt-machine-learning-specialization-scikit-learn-pitfalls":4},"\u002Fen\u002Fplaylists\u002Fmachine-learning-specialization\u002Fscikit-learn-pitfalls",{"id":5,"title":6,"body":7,"cover":1099,"date":1100,"description":1101,"extension":1102,"meta":1103,"navigation":1104,"order":1105,"path":1106,"playlist":1107,"seo":1108,"status":1109,"stem":1110,"tags":1111,"__hash__":1115},"posts\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fscikit-learn-pitfalls.md","Só pra complementar: Pegadinhas do Scikit-Learn",{"type":8,"value":9,"toc":1083},"minimark",[10,20,33,57,60,83,92,101,105,112,594,606,613,620,629,638,679,685,689,799,803,806,811,826,912,916,919,928,932,967,1034,1040,1046,1058,1062,1065,1079],[11,12,13,14,19],"p",{},"Esse post não vem de nenhuma seção obrigatória do lab, é o que sobrou depois que separei o essencial de scikit-learn e gradiente estocástico no ",[15,16,18],"a",{"href":17},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab05-scikit-learn","post principal",". São as armadilhas que só aparecem quando o código sai do notebook educacional e vai pra um projeto de verdade.",[21,22,24,28,29,32],"h2",{"id":23},"fit_transform-e-transform-não-são-a-mesma-coisa",[25,26,27],"code",{},"fit_transform"," e ",[25,30,31],{},"transform"," não são a mesma coisa",[11,34,35,36,38,39,43,44,46,47,50,51,53,54,56],{},"Esse é o ponto onde mais gente escorrega. ",[25,37,27],{}," ",[40,41,42],"strong",{},"aprende e aplica",". ",[25,45,31],{}," só ",[40,48,49],{},"aplica o que já foi aprendido",". Nos dados de treino, ",[25,52,27],{},". Em qualquer outro dado (validação, teste, produção), ",[25,55,31],{},".",[11,58,59],{},"Separei o dataset de 100 casas em 75 treino \u002F 25 teste e comparei a média do tamanho calculada dos dois jeitos:",[61,62,67],"pre",{"className":63,"code":64,"language":65,"meta":66,"style":66},"language-python shiki shiki-themes github-light github-dark","mu_certo = tamanho[treino].mean()          # certo: só o treino\nmu_errado = tamanho[teste].mean()          # errado: se eu recalculasse no teste\n","python","",[25,68,69,77],{"__ignoreMap":66},[70,71,74],"span",{"class":72,"line":73},"line",1,[70,75,76],{},"mu_certo = tamanho[treino].mean()          # certo: só o treino\n",[70,78,80],{"class":72,"line":79},2,[70,81,82],{},"mu_errado = tamanho[teste].mean()          # errado: se eu recalculasse no teste\n",[84,85,86],"blockquote",{},[11,87,88,91],{},[40,89,90],{},"Saída:"," média do treino = 1449.93, média do teste = 1305.04, diferença de 144.89",[11,93,94,95,97,98,100],{},"Se eu chamasse ",[25,96,27],{}," no teste em vez de ",[25,99,31],{},", o scaler passaria a usar 1305.04 em vez de 1449.93, uma diferença grande o bastante pra distorcer qualquer previsão feita depois. E aí a métrica de validação fica otimista demais sem eu perceber, porque o modelo \"viu\" estatística de um dado que deveria ser desconhecido.",[21,102,104],{"id":103},"sgd-sem-normalizar-simplesmente-explode","SGD sem normalizar simplesmente explode",[11,106,107,108,111],{},"Diferente do ",[25,109,110],{},"LinearRegression",", aqui normalizar não é opcional. Com features de escalas muito diferentes, o passo padrão vira um passo gigante na direção da feature de maior escala. Rodei gradiente estocástico direto nos dados crus (sem normalizar), no tamanho da casa em pés²:",[113,114,115,180],"table",{},[116,117,118],"thead",{},[119,120,121,172,176],"tr",{},[122,123,125],"th",{"align":124},"center",[70,126,129,152],{"className":127},[128],"katex",[70,130,133],{"className":131},[132],"katex-mathml",[134,135,137],"math",{"xmlns":136},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML",[138,139,140,147],"semantics",{},[141,142,143],"mrow",{},[144,145,146],"mi",{},"α",[148,149,151],"annotation",{"encoding":150},"application\u002Fx-tex","\\alpha",[70,153,157],{"className":154,"ariaHidden":156},[155],"katex-html","true",[70,158,161,166],{"className":159},[160],"base",[70,162],{"className":163,"style":165},[164],"strut","height:0.4306em;",[70,167,146],{"className":168,"style":171},[169,170],"mord","mathnormal","margin-right:0.0037em;",[122,173,175],{"align":174},"right","Passos",[122,177,179],{"align":178},"left","Resultado",[181,182,183,403],"tbody",{},[119,184,185,308,311],{},[186,187,188],"td",{"align":124},[70,189,191,225],{"className":190},[128],[70,192,194],{"className":193},[132],[134,195,196],{"xmlns":136},[138,197,198,222],{},[141,199,200,204,208],{},[201,202,203],"mn",{},"9",[205,206,207],"mo",{},"×",[209,210,211,214],"msup",{},[201,212,213],{},"10",[141,215,216,219],{},[205,217,218],{},"−",[201,220,221],{},"7",[148,223,224],{"encoding":150},"9\\times10^{-7}",[70,226,228,250],{"className":227,"ariaHidden":156},[155],[70,229,231,235,238,243,247],{"className":230},[160],[70,232],{"className":233,"style":234},[164],"height:0.7278em;vertical-align:-0.0833em;",[70,236,203],{"className":237},[169],[70,239],{"className":240,"style":242},[241],"mspace","margin-right:0.2222em;",[70,244,207],{"className":245},[246],"mbin",[70,248],{"className":249,"style":242},[241],[70,251,253,257,261],{"className":252},[160],[70,254],{"className":255,"style":256},[164],"height:0.8141em;",[70,258,260],{"className":259},[169],"1",[70,262,264,268],{"className":263},[169],[70,265,267],{"className":266},[169],"0",[70,269,272],{"className":270},[271],"msupsub",[70,273,276],{"className":274},[275],"vlist-t",[70,277,280],{"className":278},[279],"vlist-r",[70,281,284],{"className":282,"style":256},[283],"vlist",[70,285,287,292],{"style":286},"top:-3.063em;margin-right:0.05em;",[70,288],{"className":289,"style":291},[290],"pstrut","height:2.7em;",[70,293,299],{"className":294},[295,296,297,298],"sizing","reset-size6","size3","mtight",[70,300,302,305],{"className":301},[169,298],[70,303,218],{"className":304},[169,298],[70,306,221],{"className":307},[169,298],[186,309,310],{"align":174},"43",[186,312,313,316,317],{"align":178},[40,314,315],{},"diverge",", custo explode pra ",[70,318,320,344],{"className":319},[128],[70,321,323],{"className":322},[132],[134,324,325],{"xmlns":136},[138,326,327,341],{},[141,328,329,332,334],{},[201,330,331],{},"2.1",[205,333,207],{},[209,335,336,338],{},[201,337,213],{},[201,339,340],{},"6",[148,342,343],{"encoding":150},"2.1\\times10^6",[70,345,347,365],{"className":346,"ariaHidden":156},[155],[70,348,350,353,356,359,362],{"className":349},[160],[70,351],{"className":352,"style":234},[164],[70,354,331],{"className":355},[169],[70,357],{"className":358,"style":242},[241],[70,360,207],{"className":361},[246],[70,363],{"className":364,"style":242},[241],[70,366,368,371,374],{"className":367},[160],[70,369],{"className":370,"style":256},[164],[70,372,260],{"className":373},[169],[70,375,377,380],{"className":376},[169],[70,378,267],{"className":379},[169],[70,381,383],{"className":382},[271],[70,384,386],{"className":385},[275],[70,387,389],{"className":388},[279],[70,390,392],{"className":391,"style":256},[283],[70,393,394,397],{"style":286},[70,395],{"className":396,"style":291},[290],[70,398,400],{"className":399},[295,296,297,298],[70,401,340],{"className":402},[169,298],[119,404,405,501,504],{},[186,406,407],{"align":124},[70,408,410,436],{"className":409},[128],[70,411,413],{"className":412},[132],[134,414,415],{"xmlns":136},[138,416,417,433],{},[141,418,419,421,423],{},[201,420,260],{},[205,422,207],{},[209,424,425,427],{},[201,426,213],{},[141,428,429,431],{},[205,430,218],{},[201,432,221],{},[148,434,435],{"encoding":150},"1\\times10^{-7}",[70,437,439,457],{"className":438,"ariaHidden":156},[155],[70,440,442,445,448,451,454],{"className":441},[160],[70,443],{"className":444,"style":234},[164],[70,446,260],{"className":447},[169],[70,449],{"className":450,"style":242},[241],[70,452,207],{"className":453},[246],[70,455],{"className":456,"style":242},[241],[70,458,460,463,466],{"className":459},[160],[70,461],{"className":462,"style":256},[164],[70,464,260],{"className":465},[169],[70,467,469,472],{"className":468},[169],[70,470,267],{"className":471},[169],[70,473,475],{"className":474},[271],[70,476,478],{"className":477},[275],[70,479,481],{"className":480},[279],[70,482,484],{"className":483,"style":256},[283],[70,485,486,489],{"style":286},[70,487],{"className":488,"style":291},[290],[70,490,492],{"className":491},[295,296,297,298],[70,493,495,498],{"className":494},[169,298],[70,496,218],{"className":497},[169,298],[70,499,221],{"className":500},[169,298],[186,502,503],{"align":174},"200",[186,505,506,507,593],{"align":178},"estável, mas ainda longe do mínimo (custo ",[70,508,510,534],{"className":509},[128],[70,511,513],{"className":512},[132],[134,514,515],{"xmlns":136},[138,516,517,531],{},[141,518,519,522,524],{},[201,520,521],{},"1.6",[205,523,207],{},[209,525,526,528],{},[201,527,213],{},[201,529,530],{},"3",[148,532,533],{"encoding":150},"1.6\\times10^3",[70,535,537,555],{"className":536,"ariaHidden":156},[155],[70,538,540,543,546,549,552],{"className":539},[160],[70,541],{"className":542,"style":234},[164],[70,544,521],{"className":545},[169],[70,547],{"className":548,"style":242},[241],[70,550,207],{"className":551},[246],[70,553],{"className":554,"style":242},[241],[70,556,558,561,564],{"className":557},[160],[70,559],{"className":560,"style":256},[164],[70,562,260],{"className":563},[169],[70,565,567,570],{"className":566},[169],[70,568,267],{"className":569},[169],[70,571,573],{"className":572},[271],[70,574,576],{"className":575},[275],[70,577,579],{"className":578},[279],[70,580,582],{"className":581,"style":256},[283],[70,583,584,587],{"style":286},[70,585],{"className":586,"style":291},[290],[70,588,590],{"className":589},[295,296,297,298],[70,591,530],{"className":592},[169,298],")",[11,595,596,597,601,602,605],{},"O mesmo fenômeno de escala que eu já vi com gradiente batch ",[15,598,600],{"href":599},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Flab04-gradient-descent","nos posts anteriores",", só que agora no SGD. A diferença é que aqui normalizar não é só \"recomendado\", é praticamente obrigatório, e o motivo é que o SGD já chega numa situação mais frágil antes mesmo de a escala entrar em cena: cada passo usa o gradiente de ",[40,603,604],{},"um único exemplo",", não a média suavizada de todo o dataset como no batch, então o passo já pula de um jeito barulhento de exemplo pra exemplo. Multiplica esse gradiente barulhento por uma feature de escala gigante (tamanho da casa em pés², na casa dos milhares) e o tamanho do passo passa a variar violentamente de uma iteração pra outra, sem a média do batch pra absorver esse solavanco. É a mesma direção errada de sempre, só que sem o amortecedor que o batch tinha de graça.",[21,607,609,612],{"id":608},"pipeline-e-validação-cruzada-o-jeito-profissional",[25,610,611],{},"Pipeline"," e validação cruzada: o jeito profissional",[11,614,615,616,619],{},"Toda métrica que eu mostrei no post principal foi medida no ",[40,617,618],{},"treino",", ela diz o quanto o modelo decorou, não o quanto ele generaliza. E tem um segundo problema: se eu normalizar uma vez e depois fizer validação cruzada, o scaler já viu os dados de todos os folds. Vazamento de novo, só que mais sutil.",[11,621,622,624,625,628],{},[25,623,611],{}," resolve os dois: encadeia normalização e modelo num único estimador, e a cada ajuste (inclusive dentro de cada fold da validação cruzada) o scaler é reajustado ",[40,626,627],{},"só"," com a porção de treino daquele fold.",[11,630,631,632,28,634,637],{},"Rodei validação cruzada de 5 folds de verdade, comparando ",[25,633,110],{},[25,635,636],{},"Ridge(alpha=1)",":",[113,639,640,653],{},[116,641,642],{},[119,643,644,647,650],{},[122,645,646],{"align":178},"Modelo",[122,648,649],{"align":178},"R² por fold",[122,651,652],{"align":174},"Média ± desvio",[181,654,655,667],{},[119,656,657,661,664],{},[186,658,659],{"align":178},[25,660,110],{},[186,662,663],{"align":178},"0.955, 0.952, 0.915, 0.944, 0.96",[186,665,666],{"align":174},"0.9450 ± 0.0160",[119,668,669,673,676],{},[186,670,671],{"align":178},[25,672,636],{},[186,674,675],{"align":178},"0.953, 0.954, 0.919, 0.942, 0.955",[186,677,678],{"align":174},"0.9444 ± 0.0137",[11,680,681,682,684],{},"Repara que a média de validação (0.945) é menor que o R² de treino que eu citei no ",[15,683,18],{"href":17}," (0.9594), exatamente como esperado: validação sempre é mais honesta que treino. E os dois modelos ficam praticamente empatados, com 100 exemplos e 4 features não sobra capacidade demais pra Ridge precisar segurar.",[21,686,688],{"id":687},"as-outras-pegadinhas-em-lista","As outras pegadinhas, em lista",[690,691,692,708,723,741,750,768,780],"ul",{},[693,694,695,704,705,707],"li",{},[40,696,697,700,701],{},[25,698,699],{},"intercept_"," é um array no ",[25,702,703],{},"SGDRegressor"," e um escalar no ",[25,706,110],{},". Código que assume um dos dois formatos quebra no outro.",[693,709,710,716,717,719,720,56],{},[40,711,712,715],{},[25,713,714],{},"max_iter"," é um teto, não uma meta"," (já vimos no ",[15,718,18],{"href":17},"). Sempre confira ",[25,721,722],{},"n_iter_",[693,724,725,731,732,734,735,737,738,56],{},[40,726,727,730],{},[25,728,729],{},"penalty='l2'"," vem ligado por padrão"," no ",[25,733,703],{}," (",[15,736,18],{"href":17},"). Pra mínimos quadrados puros, passe ",[25,739,740],{},"penalty=None",[693,742,743,749],{},[40,744,745,748],{},[25,746,747],{},"random_state"," não é opcional"," se você quer reproduzir resultado.",[693,751,752,757,758,760,761,764,765,767],{},[40,753,754],{},[25,755,756],{},"ConvergenceWarning"," significa que o modelo bateu no ",[25,759,714],{}," sem satisfazer o ",[25,762,763],{},"tol",". Não ignora: aumenta ",[25,766,714],{},", ajusta a taxa de aprendizado, ou confere se normalizou.",[693,769,770,776,777,779],{},[40,771,772,773],{},"Normalizar o alvo ",[25,774,775],{},"y"," não é feito automaticamente por nada disso. Se ",[25,778,775],{}," tiver magnitude extrema, considere normalizar, e lembre de desnormalizar as previsões antes de reportar qualquer métrica.",[693,781,782,788,789,792,793,795,796,798],{},[40,783,784,787],{},[25,785,786],{},"fit"," reinicia o modelo do zero."," Pra treino incremental, com dado chegando aos poucos (em vez de tudo de uma vez), existe ",[25,790,791],{},"partial_fit",": o modelo se atualiza sem nunca precisar ver o dataset inteiro junto. É o caso de uso real por trás de \"dado que não cabe na memória\" que mencionei no ",[15,794,18],{"href":17},", e é literalmente o que o simulador estocástico do ",[15,797,18],{"href":17}," já mostra: cada passo enxerga uma casa só, nunca o dataset inteiro de uma vez, e ainda assim o modelo caminha pro mesmo lugar que o batch.",[21,800,802],{"id":801},"exercícios","Exercícios",[11,804,805],{},"Tenta antes de abrir a resposta.",[807,808,810],"h3",{"id":809},"exercício-1-reproduza-o-normalizador","Exercício 1: reproduza o normalizador",[11,812,813,814,816,817,28,819,821,822,56],{},"Implementa uma versão sua de normalização por z-score com os métodos ",[25,815,786],{},", ",[25,818,31],{},[25,820,27],{},", seguindo a convenção de atributos com underscore no fim. Confere que bate com o resultado do ",[15,823,825],{"href":824},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab03-feature-scaling","post de normalização",[827,828,829,836,899],"details",{},[830,831,832],"summary",{},[833,834,835],"b",{},"Resposta",[61,837,839],{"className":63,"code":838,"language":65,"meta":66,"style":66},"class MeuScaler:\n    def fit(self, X):\n        self.mean_ = X.mean(axis=0)\n        self.scale_ = X.std(axis=0)\n        self.scale_[self.scale_ == 0] = 1.0\n        return self\n    def transform(self, X):\n        return (X - self.mean_) \u002F self.scale_\n    def fit_transform(self, X):\n        return self.fit(X).transform(X)\n",[25,840,841,846,851,857,863,869,875,881,887,893],{"__ignoreMap":66},[70,842,843],{"class":72,"line":73},[70,844,845],{},"class MeuScaler:\n",[70,847,848],{"class":72,"line":79},[70,849,850],{},"    def fit(self, X):\n",[70,852,854],{"class":72,"line":853},3,[70,855,856],{},"        self.mean_ = X.mean(axis=0)\n",[70,858,860],{"class":72,"line":859},4,[70,861,862],{},"        self.scale_ = X.std(axis=0)\n",[70,864,866],{"class":72,"line":865},5,[70,867,868],{},"        self.scale_[self.scale_ == 0] = 1.0\n",[70,870,872],{"class":72,"line":871},6,[70,873,874],{},"        return self\n",[70,876,878],{"class":72,"line":877},7,[70,879,880],{},"    def transform(self, X):\n",[70,882,884],{"class":72,"line":883},8,[70,885,886],{},"        return (X - self.mean_) \u002F self.scale_\n",[70,888,890],{"class":72,"line":889},9,[70,891,892],{},"    def fit_transform(self, X):\n",[70,894,896],{"class":72,"line":895},10,[70,897,898],{},"        return self.fit(X).transform(X)\n",[11,900,901,902,731,905,907,908,911],{},"Devolver ",[25,903,904],{},"self",[25,906,786],{}," é o que permite encadear ",[25,909,910],{},"MeuScaler().fit(X).transform(X)",", o mesmo padrão que todo transformador do scikit-learn segue.",[807,913,915],{"id":914},"exercício-2-o-efeito-da-taxa-de-aprendizado-no-sgd","Exercício 2: o efeito da taxa de aprendizado no SGD",[11,917,918],{},"Roda o gradiente estocástico com taxa constante em vários valores. O que acontece nos dois extremos?",[827,920,921,925],{},[830,922,923],{},[833,924,835],{},[11,926,927],{},"Com taxa pequena demais, o modelo não chega perto do mínimo dentro do número de passos disponível. Com taxa grande demais, diverge, igual eu mostrei nesse post com os dados crus. Uma taxa que decresce ao longo do treino (o padrão do scikit-learn) existe justamente pra não precisar acertar isso na mão: começa maior, dá passo grande no início quando ainda tá longe, e encolhe conforme se aproxima.",[807,929,931],{"id":930},"exercício-3-quanto-o-ridge-escondido-está-custando","Exercício 3: quanto o Ridge escondido está custando?",[11,933,934,935,937,938,966],{},"Compara ",[25,936,740],{}," com vários valores de ",[70,939,941,954],{"className":940},[128],[70,942,944],{"className":943},[132],[134,945,946],{"xmlns":136},[138,947,948,952],{},[141,949,950],{},[144,951,146],{},[148,953,151],{"encoding":150},[70,955,957],{"className":956,"ariaHidden":156},[155],[70,958,960,963],{"className":959},[160],[70,961],{"className":962,"style":165},[164],[70,964,146],{"className":965,"style":171},[169,170]," usando validação cruzada. Em que ponto a regularização começa a atrapalhar? E se o dataset tivesse só 20 exemplos em vez de 100?",[827,968,969,973],{},[830,970,971],{},[833,972,835],{},[11,974,975,976,1004,1005,1033],{},"Com 100 exemplos e 4 features não há capacidade sobrando, então qualquer ",[70,977,979,992],{"className":978},[128],[70,980,982],{"className":981},[132],[134,983,984],{"xmlns":136},[138,985,986,990],{},[141,987,988],{},[144,989,146],{},[148,991,151],{"encoding":150},[70,993,995],{"className":994,"ariaHidden":156},[155],[70,996,998,1001],{"className":997},[160],[70,999],{"className":1000,"style":165},[164],[70,1002,146],{"className":1003,"style":171},[169,170]," grande só atrapalha. Com 20 exemplos a história muda: a razão exemplos\u002Fparâmetros fica apertada, e um ",[70,1006,1008,1021],{"className":1007},[128],[70,1009,1011],{"className":1010},[132],[134,1012,1013],{"xmlns":136},[138,1014,1015,1019],{},[141,1016,1017],{},[144,1018,146],{},[148,1020,151],{"encoding":150},[70,1022,1024],{"className":1023,"ariaHidden":156},[155],[70,1025,1027,1030],{"className":1026},[160],[70,1028],{"className":1029,"style":165},[164],[70,1031,146],{"className":1032,"style":171},[169,170]," moderado passa a ajudar de verdade. A lição de sempre: regularização não é boa nem ruim em si, é resposta a um excesso de capacidade que pode ou não existir no seu dado.",[807,1035,1037,1038],{"id":1036},"exercício-4-validação-cruzada-com-e-sem-pipeline","Exercício 4: validação cruzada com e sem ",[25,1039,611],{},[11,1041,1042,1043,1045],{},"Compara o R² de validação cruzada em dois cenários: normalizando uma vez antes e passando o resultado pra validação cruzada, contra usando um ",[25,1044,611],{},". Os números batem?",[827,1047,1048,1052],{},[830,1049,1050],{},[833,1051,835],{},[11,1053,1054,1055,1057],{},"Nesse dataset a diferença é pequena, porque os folds são parecidos entre si. Mas o primeiro cenário está conceitualmente errado: o normalizador viu os dados de validação. Em dataset pequeno, com outlier, ou com estrutura temporal, essa diferença deixa de ser pequena. Usa ",[25,1056,611],{}," sempre, não porque o número muda muito hoje, mas porque ele torna o erro impossível de cometer sem querer.",[807,1059,1061],{"id":1060},"exercício-5-o-modelo-generaliza-pra-casas-fora-da-faixa","Exercício 5: o modelo generaliza pra casas fora da faixa?",[11,1063,1064],{},"Separa as 20 casas mais caras como teste e treina nas 80 restantes. O que acontece com o R² de teste?",[827,1066,1067,1071],{},[830,1068,1069],{},[833,1070,835],{},[11,1072,1073,1074,1078],{},"O R² despenca, e pode até ficar negativo. O motivo não é overfitting, é que a divisão não é aleatória: o teste ficou sistematicamente diferente do treino (extrapolação, o mesmo problema que eu vi com polinômio no ",[15,1075,1077],{"href":1076},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab04-feature-engineering","post de engenharia de features","). Divisão aleatória supõe que os dados são intercambiáveis, quando não são (tempo, geografia, faixa de preço), a divisão precisa respeitar isso.",[1080,1081,1082],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":66,"searchDepth":79,"depth":79,"links":1084},[1085,1087,1088,1090,1091],{"id":23,"depth":79,"text":1086},"fit_transform e transform não são a mesma coisa",{"id":103,"depth":79,"text":104},{"id":608,"depth":79,"text":1089},"Pipeline e validação cruzada: o jeito profissional",{"id":687,"depth":79,"text":688},{"id":801,"depth":79,"text":802,"children":1092},[1093,1094,1095,1096,1098],{"id":809,"depth":853,"text":810},{"id":914,"depth":853,"text":915},{"id":930,"depth":853,"text":931},{"id":1036,"depth":853,"text":1097},"Exercício 4: validação cruzada com e sem Pipeline",{"id":1060,"depth":853,"text":1061},null,"2026-08-19","Vazamento de dado entre fit_transform e transform, SGD explodindo sem normalizar, Pipeline com validação cruzada de verdade, e as pegadinhas de API que travam quem tá começando.","md",{},true,11,"\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fscikit-learn-pitfalls","machine-learning-specialization",{"title":6,"description":1101},"draft","pt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fscikit-learn-pitfalls",[1112,1113,1114],"scikit-learn","pipeline","validacao-cruzada","UeWDlpAmQaIJLEw1pfjQTo-nEADDdz2Y973kFoRTGaQ",1787338985058]