[{"data":1,"prerenderedAt":2189},["ShallowReactive",2],{"lang-switch-post-\u002Fplaylists\u002Fmachine-learning-specialization\u002Ffeature-scaling-pitfalls":3,"post-pt-machine-learning-specialization-feature-scaling-pitfalls":4},"\u002Fen\u002Fplaylists\u002Fmachine-learning-specialization\u002Ffeature-scaling-pitfalls",{"id":5,"title":6,"body":7,"cover":2174,"date":2175,"description":2176,"extension":2177,"meta":2178,"navigation":732,"order":746,"path":2179,"playlist":2180,"seo":2181,"status":2182,"stem":2183,"tags":2184,"__hash__":2188},"posts\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Ffeature-scaling-pitfalls.md","Só pra complementar: Pegadinhas de Normalização",{"type":8,"value":9,"toc":2160},"minimark",[10,20,25,109,112,135,145,181,199,203,335,350,359,398,412,444,448,482,488,553,557,560,575,691,703,708,762,772,869,873,876,881,1068,1339,1343,1428,1663,1667,1801,1868,1901,2004,2091,2095,2102,2156],[11,12,13,14,19],"p",{},"Esse post não vem de nenhuma seção obrigatória do lab, é o que sobrou depois que eu separei o essencial de normalização no ",[15,16,18],"a",{"href":17},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab03-feature-scaling","post principal",". São as pegadinhas que eu só ia esbarrar mesmo num projeto de verdade, fora do conforto de um notebook educacional.",[21,22,24],"h2",{"id":23},"vazamento-de-dado-normalizar-antes-de-separar-treino-e-teste","Vazamento de dado: normalizar antes de separar treino e teste",[11,26,27,28,75,76,108],{},"O erro mais comum de todos. Se eu calculo ",[29,30,33,56],"span",{"className":31},[32],"katex",[29,34,37],{"className":35},[36],"katex-mathml",[38,39,41],"math",{"xmlns":40},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML",[42,43,44,51],"semantics",{},[45,46,47],"mrow",{},[48,49,50],"mi",{},"μ",[52,53,55],"annotation",{"encoding":54},"application\u002Fx-tex","\\mu",[29,57,61],{"className":58,"ariaHidden":60},[59],"katex-html","true",[29,62,65,70],{"className":63},[64],"base",[29,66],{"className":67,"style":69},[68],"strut","height:0.625em;vertical-align:-0.1944em;",[29,71,50],{"className":72},[73,74],"mord","mathnormal"," e ",[29,77,79,94],{"className":78},[32],[29,80,82],{"className":81},[36],[38,83,84],{"xmlns":40},[42,85,86,91],{},[45,87,88],{},[48,89,90],{},"σ",[52,92,93],{"encoding":54},"\\sigma",[29,95,97],{"className":96,"ariaHidden":60},[59],[29,98,100,104],{"className":99},[64],[29,101],{"className":102,"style":103},[68],"height:0.4306em;",[29,105,90],{"className":106,"style":107},[73,74],"margin-right:0.0359em;"," usando o dataset inteiro (treino + teste juntos) antes de separar, informação do conjunto de teste vaza pro treino, e minha métrica de validação fica otimista demais sem eu perceber.",[11,110,111],{},"Separei o dataset de 100 casas em 80 treino \u002F 20 teste e comparei a média do tamanho calculada dos dois jeitos:",[113,114,119],"pre",{"className":115,"code":116,"language":117,"meta":118,"style":118},"language-python shiki shiki-themes github-light github-dark","mu_todos = X_train.mean(axis=0)        # ERRADO: usa treino + teste\nmu_so_treino = X_train[i_tr].mean(axis=0)  # CERTO: só o treino\n","python","",[120,121,122,129],"code",{"__ignoreMap":118},[29,123,126],{"class":124,"line":125},"line",1,[29,127,128],{},"mu_todos = X_train.mean(axis=0)        # ERRADO: usa treino + teste\n",[29,130,132],{"class":124,"line":131},2,[29,133,134],{},"mu_so_treino = X_train[i_tr].mean(axis=0)  # CERTO: só o treino\n",[136,137,138],"blockquote",{},[11,139,140,144],{},[141,142,143],"strong",{},"Saída:"," média com tudo junto = 1413.7, média só do treino = 1385.3, diferença de 28.4.",[11,146,147,148,176,177,180],{},"Não parece muito, mas plantei um cenário pior: uma casa gigante de 9000 pés² aparecendo só no conjunto de teste. Se eu calculasse ",[29,149,151,164],{"className":150},[32],[29,152,154],{"className":153},[36],[38,155,156],{"xmlns":40},[42,157,158,162],{},[45,159,160],{},[48,161,50],{},[52,163,55],{"encoding":54},[29,165,167],{"className":166,"ariaHidden":60},[59],[29,168,170,173],{"className":169},[64],[29,171],{"className":172,"style":69},[68],[29,174,50],{"className":175},[73,74]," com o dataset inteiro (incluindo essa casa \"invisível\" que deveria estar trancada no teste), a média pularia pra 1488.8, um desvio de mais de 100 unidades só por causa de ",[141,178,179],{},"uma"," linha que eu não deveria nem ter olhado ainda.",[11,182,183,186,187,190,191,194,195,198],{},[141,184,185],{},"Regra que eu levo comigo:"," ",[120,188,189],{},"fit"," só no treino, ",[120,192,193],{},"transform"," em todo mundo. Isso vale pra qualquer coisa que aprende estatística dos dados antes de usar (normalização, redução de dimensionalidade, seleção de feature), não só pra regressão linear. O ",[120,196,197],{},"Pipeline"," do scikit-learn (que eu mostro mais embaixo) existe basicamente pra tornar esse erro impossível de cometer sem querer.",[21,200,202],{"id":201},"feature-constante-divisão-por-zero","Feature constante: divisão por zero",[11,204,205,206,326,327,330,331,334],{},"Se uma coluna tem ",[29,207,209,237],{"className":208},[32],[29,210,212],{"className":211},[36],[38,213,214],{"xmlns":40},[42,215,216,234],{},[45,217,218,226,230],{},[219,220,221,223],"msub",{},[48,222,90],{},[48,224,225],{},"j",[227,228,229],"mo",{},"=",[231,232,233],"mn",{},"0",[52,235,236],{"encoding":54},"\\sigma_j = 0",[29,238,240,316],{"className":239,"ariaHidden":60},[59],[29,241,243,247,304,309,313],{"className":242},[64],[29,244],{"className":245,"style":246},[68],"height:0.7167em;vertical-align:-0.2861em;",[29,248,250,253],{"className":249},[73],[29,251,90],{"className":252,"style":107},[73,74],[29,254,257],{"className":255},[256],"msupsub",[29,258,262,295],{"className":259},[260,261],"vlist-t","vlist-t2",[29,263,266,290],{"className":264},[265],"vlist-r",[29,267,271],{"className":268,"style":270},[269],"vlist","height:0.3117em;",[29,272,274,279],{"style":273},"top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;",[29,275],{"className":276,"style":278},[277],"pstrut","height:2.7em;",[29,280,286],{"className":281},[282,283,284,285],"sizing","reset-size6","size3","mtight",[29,287,225],{"className":288,"style":289},[73,74,285],"margin-right:0.0572em;",[29,291,294],{"className":292},[293],"vlist-s","​",[29,296,298],{"className":297},[265],[29,299,302],{"className":300,"style":301},[269],"height:0.2861em;",[29,303],{},[29,305],{"className":306,"style":308},[307],"mspace","margin-right:0.2778em;",[29,310,229],{"className":311},[312],"mrel",[29,314],{"className":315,"style":308},[307],[29,317,319,323],{"className":318},[64],[29,320],{"className":321,"style":322},[68],"height:0.6444em;",[29,324,233],{"className":325},[73]," (todo mundo com o mesmo valor), a fórmula de z-score divide por zero e gera ",[120,328,329],{},"inf"," ou ",[120,332,333],{},"nan",".",[113,336,338],{"className":115,"code":337,"language":117,"meta":118,"style":118},"mu, sigma = 1413.71, 0.0   # sigma zerado, coluna constante\n(1500 - mu) \u002F sigma\n",[120,339,340,345],{"__ignoreMap":118},[29,341,342],{"class":124,"line":125},[29,343,344],{},"mu, sigma = 1413.71, 0.0   # sigma zerado, coluna constante\n",[29,346,347],{"class":124,"line":131},[29,348,349],{},"(1500 - mu) \u002F sigma\n",[136,351,352],{},[11,353,354,186,357],{},[141,355,356],{},"Saída sem proteção:",[120,358,329],{},[113,360,362],{"className":115,"code":361,"language":117,"meta":118,"style":118},"def zscore_seguro(X, eps=1e-12):\n    mu = X.mean(axis=0)\n    sigma = X.std(axis=0)\n    constantes = sigma \u003C eps\n    sigma_safe = np.where(constantes, 1.0, sigma)  # forca sigma=1 nas colunas constantes\n    return (X - mu) \u002F sigma_safe, mu, sigma_safe\n",[120,363,364,369,374,380,386,392],{"__ignoreMap":118},[29,365,366],{"class":124,"line":125},[29,367,368],{},"def zscore_seguro(X, eps=1e-12):\n",[29,370,371],{"class":124,"line":131},[29,372,373],{},"    mu = X.mean(axis=0)\n",[29,375,377],{"class":124,"line":376},3,[29,378,379],{},"    sigma = X.std(axis=0)\n",[29,381,383],{"class":124,"line":382},4,[29,384,385],{},"    constantes = sigma \u003C eps\n",[29,387,389],{"class":124,"line":388},5,[29,390,391],{},"    sigma_safe = np.where(constantes, 1.0, sigma)  # forca sigma=1 nas colunas constantes\n",[29,393,395],{"class":124,"line":394},6,[29,396,397],{},"    return (X - mu) \u002F sigma_safe, mu, sigma_safe\n",[136,399,400],{},[11,401,402,186,405,408,409,411],{},[141,403,404],{},"Saída com proteção:",[120,406,407],{},"86.29"," (a coluna constante vira zero em vez de ",[120,410,329],{},", sem quebrar o resto da conta)",[11,413,414,415,443],{},"Uma coluna constante não carrega informação nenhuma pro modelo de qualquer forma, então travar o ",[29,416,418,431],{"className":417},[32],[29,419,421],{"className":420},[36],[38,422,423],{"xmlns":40},[42,424,425,429],{},[45,426,427],{},[48,428,90],{},[52,430,93],{"encoding":54},[29,432,434],{"className":433,"ariaHidden":60},[59],[29,435,437,440],{"className":436},[64],[29,438],{"className":439,"style":103},[68],[29,441,90],{"className":442,"style":107},[73,74]," em 1 é só uma forma segura de \"desligar\" essa feature sem derrubar o programa inteiro.",[21,445,447],{"id":446},"quando-eu-não-normalizo","Quando eu NÃO normalizo",[449,450,451,458,473],"ul",{},[452,453,454,457],"li",{},[141,455,456],{},"Árvore de decisão, Random Forest, Gradient Boosting:"," esses modelos dividem por limiares em cada feature isolada. Escala não importa nada pra eles, normalizar só gasta tempo de processamento à toa.",[452,459,460,467,468,472],{},[141,461,462,463,466],{},"Equação normal \u002F ",[120,464,465],{},"LinearRegression",":"," resolve em forma fechada, sem passo iterativo nenhum. Não ",[469,470,471],"em",{},"precisa"," de normalização (embora escalas muito extremas ainda possam causar problema numérico de precisão).",[452,474,475,478,479,481],{},[141,476,477],{},"Quando a unidade importa pra interpretação:"," se eu preciso dizer \"cada pé² a mais vale X dólares\", tenho que desnormalizar os coeficientes de volta (fiz isso no ",[15,480,18],{"href":17},", seção de desnormalização).",[11,483,484,487],{},[141,485,486],{},"Sempre normalizo"," pra: gradiente descendente, SVM, k-NN, k-means, PCA, rede neural, e qualquer modelo com regularização L1\u002FL2 (senão a penalidade cai injustamente em cima das features de escala pequena).",[11,489,490,491,520,521,549,550,552],{},"E o alvo ",[29,492,494,508],{"className":493},[32],[29,495,497],{"className":496},[36],[38,498,499],{"xmlns":40},[42,500,501,506],{},[45,502,503],{},[48,504,505],{},"y",[52,507,505],{"encoding":54},[29,509,511],{"className":510,"ariaHidden":60},[59],[29,512,514,517],{"className":513},[64],[29,515],{"className":516,"style":69},[68],[29,518,505],{"className":519,"style":107},[73,74],"? Não é obrigatório normalizar pra regressão linear com gradiente descendente, mas ajuda se ",[29,522,524,537],{"className":523},[32],[29,525,527],{"className":526},[36],[38,528,529],{"xmlns":40},[42,530,531,535],{},[45,532,533],{},[48,534,505],{},[52,536,505],{"encoding":54},[29,538,540],{"className":539,"ariaHidden":60},[59],[29,541,543,546],{"className":542},[64],[29,544],{"className":545,"style":69},[68],[29,547,505],{"className":548,"style":107},[73,74]," tiver magnitude muito grande (evita ",[120,551,329],{}," no custo). Se eu normalizar o alvo, preciso lembrar de desnormalizar as previsões antes de reportar qualquer métrica pra alguém.",[21,554,556],{"id":555},"conferindo-com-uma-solução-exata","Conferindo com uma solução exata",[11,558,559],{},"Minha implementação de gradiente descendente está certa? Eu não preciso confiar cegamente. Regressão linear tem solução fechada (a equação normal), então dá pra comparar meu resultado iterativo contra a resposta exata.",[113,561,563],{"className":115,"code":562,"language":117,"meta":118,"style":118},"theta_exato = np.linalg.lstsq(X_aug, y_train, rcond=None)[0]\nw_exato, b_exato = theta_exato[:4], theta_exato[4]\n",[120,564,565,570],{"__ignoreMap":118},[29,566,567],{"class":124,"line":125},[29,568,569],{},"theta_exato = np.linalg.lstsq(X_aug, y_train, rcond=None)[0]\n",[29,571,572],{"class":124,"line":131},[29,573,574],{},"w_exato, b_exato = theta_exato[:4], theta_exato[4]\n",[11,576,577,578,580,581,635,636,690],{},"No ",[15,579,18],{"href":17}," eu já mostrei que, com uma feature só, desnormalizar o resultado do meu gradiente descendente (",[29,582,584,604],{"className":583},[32],[29,585,587],{"className":586},[36],[38,588,589],{"xmlns":40},[42,590,591,601],{},[45,592,593,596,598],{},[48,594,595],{},"w",[227,597,229],{},[231,599,600],{},"0.267",[52,602,603],{"encoding":54},"w = 0.267",[29,605,607,626],{"className":606,"ariaHidden":60},[59],[29,608,610,613,617,620,623],{"className":609},[64],[29,611],{"className":612,"style":103},[68],[29,614,595],{"className":615,"style":616},[73,74],"margin-right:0.0269em;",[29,618],{"className":619,"style":308},[307],[29,621,229],{"className":622},[312],[29,624],{"className":625,"style":308},[307],[29,627,629,632],{"className":628},[64],[29,630],{"className":631,"style":322},[68],[29,633,600],{"className":634},[73],", ",[29,637,639,659],{"className":638},[32],[29,640,642],{"className":641},[36],[38,643,644],{"xmlns":40},[42,645,646,656],{},[45,647,648,651,653],{},[48,649,650],{},"b",[227,652,229],{},[231,654,655],{},"7.16",[52,657,658],{"encoding":54},"b = 7.16",[29,660,662,681],{"className":661,"ariaHidden":60},[59],[29,663,665,669,672,675,678],{"className":664},[64],[29,666],{"className":667,"style":668},[68],"height:0.6944em;",[29,670,650],{"className":671},[73,74],[29,673],{"className":674,"style":308},[307],[29,676,229],{"className":677},[312],[29,679],{"className":680,"style":308},[307],[29,682,684,687],{"className":683},[64],[29,685],{"className":686,"style":322},[68],[29,688,655],{"className":689},[73],") bate dígito a dígito com o que a fórmula fechada dá direto em espaço cru. Fiz a mesma checagem com as 4 features de verdade: o custo mínimo teórico da equação normal e o custo do meu gradiente descendente depois de 1000 iterações ficam a uma distância desprezível um do outro. As duas contas concordam, o que me deixa bem mais confiante de que não escrevi nenhum bug silencioso na implementação.",[136,692,693],{},[11,694,695,696,698,699,702],{},"Não tenho o scikit-learn instalado nesse ambiente pra rodar um terceiro método de comparação (",[120,697,465],{},"\u002F",[120,700,701],{},"SGDRegressor","), mas o princípio é o mesmo do notebook original: rodar a mesma conta por métodos independentes e conferir se todos concordam é a forma mais barata de pegar um bug de implementação antes de confiar num número.",[11,704,705,706,466],{},"O jeito idiomático de fazer tudo isso em produção é um ",[120,707,197],{},[113,709,711],{"className":115,"code":710,"language":117,"meta":118,"style":118},"from sklearn.preprocessing import StandardScaler\nfrom sklearn.linear_model import SGDRegressor\nfrom sklearn.pipeline import make_pipeline\n\npipe = make_pipeline(\n    StandardScaler(),                                   # equivale ao meu zscore_normalize_features\n    SGDRegressor(max_iter=2000, tol=1e-6, eta0=0.1),\n)\npipe.fit(X_train, y_train)\n",[120,712,713,718,723,728,734,739,744,750,756],{"__ignoreMap":118},[29,714,715],{"class":124,"line":125},[29,716,717],{},"from sklearn.preprocessing import StandardScaler\n",[29,719,720],{"class":124,"line":131},[29,721,722],{},"from sklearn.linear_model import SGDRegressor\n",[29,724,725],{"class":124,"line":376},[29,726,727],{},"from sklearn.pipeline import make_pipeline\n",[29,729,730],{"class":124,"line":382},[29,731,733],{"emptyLinePlaceholder":732},true,"\n",[29,735,736],{"class":124,"line":388},[29,737,738],{},"pipe = make_pipeline(\n",[29,740,741],{"class":124,"line":394},[29,742,743],{},"    StandardScaler(),                                   # equivale ao meu zscore_normalize_features\n",[29,745,747],{"class":124,"line":746},7,[29,748,749],{},"    SGDRegressor(max_iter=2000, tol=1e-6, eta0=0.1),\n",[29,751,753],{"class":124,"line":752},8,[29,754,755],{},")\n",[29,757,759],{"class":124,"line":758},9,[29,760,761],{},"pipe.fit(X_train, y_train)\n",[11,763,764,765,767,768,771],{},"O ",[120,766,197],{}," garante que o ",[120,769,770],{},"StandardScaler"," só é ajustado no treino em cada fold de validação, eliminando vazamento de dado automaticamente. É a forma correta de fazer isso na prática, em vez de normalizar na mão como eu fiz nesse post pra entender a mecânica por baixo.",[11,773,774,780,781,868],{},[141,775,776,777,779],{},"Por que aprender gradiente descendente, se ",[120,778,465],{}," resolve exato?"," Porque a equação normal só existe pra modelos lineares, e custa ",[29,782,784,815],{"className":783},[32],[29,785,787],{"className":786},[36],[38,788,789],{"xmlns":40},[42,790,791,812],{},[45,792,793,796,800,809],{},[48,794,795],{},"O",[227,797,799],{"stretchy":798},"false","(",[801,802,803,806],"msup",{},[48,804,805],{},"n",[231,807,808],{},"3",[227,810,811],{"stretchy":798},")",[52,813,814],{"encoding":54},"O(n^3)",[29,816,818],{"className":817,"ariaHidden":60},[59],[29,819,821,825,829,833,864],{"className":820},[64],[29,822],{"className":823,"style":824},[68],"height:1.0641em;vertical-align:-0.25em;",[29,826,795],{"className":827,"style":828},[73,74],"margin-right:0.0278em;",[29,830,799],{"className":831},[832],"mopen",[29,834,836,839],{"className":835},[73],[29,837,805],{"className":838},[73,74],[29,840,842],{"className":841},[256],[29,843,845],{"className":844},[260],[29,846,848],{"className":847},[265],[29,849,852],{"className":850,"style":851},[269],"height:0.8141em;",[29,853,855,858],{"style":854},"top:-3.063em;margin-right:0.05em;",[29,856],{"className":857,"style":278},[277],[29,859,861],{"className":860},[282,283,284,285],[29,862,808],{"className":863},[73,285],[29,865,811],{"className":866},[867],"mclose"," pra inverter a matriz, inviável com milhões de features. Gradiente descendente é o algoritmo que de fato treina rede neural, regressão logística, SVM e praticamente tudo mais. Regressão linear é só o playground onde dá pra ver a mecânica funcionando com uma resposta exata pra conferir.",[21,870,872],{"id":871},"exercícios","Exercícios",[11,874,875],{},"Tenta antes de abrir a resposta.",[877,878,880],"h3",{"id":879},"exercício-1-sensibilidade-à-unidade","Exercício 1: sensibilidade à unidade",[11,882,883,884,887,888,1015,1016,334],{},"Converte ",[120,885,886],{},"size"," de pés² pra metros quadrados (1 pé² = 0.092903 m²) e roda o gradiente descendente nos dados crus com ",[29,889,891,927],{"className":890},[32],[29,892,894],{"className":893},[36],[38,895,896],{"xmlns":40},[42,897,898,924],{},[45,899,900,903,905,908,911],{},[48,901,902],{},"α",[227,904,229],{},[231,906,907],{},"9",[227,909,910],{},"×",[801,912,913,916],{},[231,914,915],{},"10",[45,917,918,921],{},[227,919,920],{},"−",[231,922,923],{},"7",[52,925,926],{"encoding":54},"\\alpha = 9\\times10^{-7}",[29,928,930,949,970],{"className":929,"ariaHidden":60},[59],[29,931,933,936,940,943,946],{"className":932},[64],[29,934],{"className":935,"style":103},[68],[29,937,902],{"className":938,"style":939},[73,74],"margin-right:0.0037em;",[29,941],{"className":942,"style":308},[307],[29,944,229],{"className":945},[312],[29,947],{"className":948,"style":308},[307],[29,950,952,956,959,963,967],{"className":951},[64],[29,953],{"className":954,"style":955},[68],"height:0.7278em;vertical-align:-0.0833em;",[29,957,907],{"className":958},[73],[29,960],{"className":961,"style":962},[307],"margin-right:0.2222em;",[29,964,910],{"className":965},[966],"mbin",[29,968],{"className":969,"style":962},[307],[29,971,973,976,980],{"className":972},[64],[29,974],{"className":975,"style":851},[68],[29,977,979],{"className":978},[73],"1",[29,981,983,986],{"className":982},[73],[29,984,233],{"className":985},[73],[29,987,989],{"className":988},[256],[29,990,992],{"className":991},[260],[29,993,995],{"className":994},[265],[29,996,998],{"className":997,"style":851},[269],[29,999,1000,1003],{"style":854},[29,1001],{"className":1002,"style":278},[277],[29,1004,1006],{"className":1005},[282,283,284,285],[29,1007,1009,1012],{"className":1008},[73,285],[29,1010,920],{"className":1011},[73,285],[29,1013,923],{"className":1014},[73,285],". O que acontece? Depois normaliza e roda com ",[29,1017,1019,1038],{"className":1018},[32],[29,1020,1022],{"className":1021},[36],[38,1023,1024],{"xmlns":40},[42,1025,1026,1035],{},[45,1027,1028,1030,1032],{},[48,1029,902],{},[227,1031,229],{},[231,1033,1034],{},"0.1",[52,1036,1037],{"encoding":54},"\\alpha = 0.1",[29,1039,1041,1059],{"className":1040,"ariaHidden":60},[59],[29,1042,1044,1047,1050,1053,1056],{"className":1043},[64],[29,1045],{"className":1046,"style":103},[68],[29,1048,902],{"className":1049,"style":939},[73,74],[29,1051],{"className":1052,"style":308},[307],[29,1054,229],{"className":1055},[312],[29,1057],{"className":1058,"style":308},[307],[29,1060,1062,1065],{"className":1061},[64],[29,1063],{"className":1064,"style":322},[68],[29,1066,1034],{"className":1067},[73],[1069,1070,1071,1077],"details",{},[1072,1073,1074],"summary",{},[650,1075,1076],{},"Resposta",[11,1078,1079,1080,1082,1083,1113,1114,1143,1144,1172,1173,1176,1177,1338],{},"Nos dados crus, mudar a unidade muda a escala de ",[120,1081,886],{}," por uns 10x, o que muda ",[29,1084,1086,1100],{"className":1085},[32],[29,1087,1089],{"className":1088},[36],[38,1090,1091],{"xmlns":40},[42,1092,1093,1098],{},[45,1094,1095],{},[48,1096,1097],{},"L",[52,1099,1097],{"encoding":54},[29,1101,1103],{"className":1102,"ariaHidden":60},[59],[29,1104,1106,1110],{"className":1105},[64],[29,1107],{"className":1108,"style":1109},[68],"height:0.6833em;",[29,1111,1097],{"className":1112},[73,74]," e portanto o ",[29,1115,1117,1131],{"className":1116},[32],[29,1118,1120],{"className":1119},[36],[38,1121,1122],{"xmlns":40},[42,1123,1124,1128],{},[45,1125,1126],{},[48,1127,902],{},[52,1129,1130],{"encoding":54},"\\alpha",[29,1132,1134],{"className":1133,"ariaHidden":60},[59],[29,1135,1137,1140],{"className":1136},[64],[29,1138],{"className":1139,"style":103},[68],[29,1141,902],{"className":1142,"style":939},[73,74]," crítico. O ",[29,1145,1147,1160],{"className":1146},[32],[29,1148,1150],{"className":1149},[36],[38,1151,1152],{"xmlns":40},[42,1153,1154,1158],{},[45,1155,1156],{},[48,1157,902],{},[52,1159,1130],{"encoding":54},[29,1161,1163],{"className":1162,"ariaHidden":60},[59],[29,1164,1166,1169],{"className":1165},[64],[29,1167],{"className":1168,"style":103},[68],[29,1170,902],{"className":1171,"style":939},[73,74]," que funcionava antes pode passar a divergir ou ficar lentíssimo. Nos dados normalizados ",[141,1174,1175],{},"nada muda",": z-score é invariante a mudança de unidade linear, porque ",[29,1178,1180,1234],{"className":1179},[32],[29,1181,1183],{"className":1182},[36],[38,1184,1185],{"xmlns":40},[42,1186,1187,1231],{},[45,1188,1189,1191,1193,1196,1198,1200,1202,1204,1207,1209,1211,1213,1215,1217,1219,1221,1223,1225,1227,1229],{},[227,1190,799],{"stretchy":798},[48,1192,15],{},[48,1194,1195],{},"x",[227,1197,920],{},[48,1199,15],{},[48,1201,50],{},[227,1203,811],{"stretchy":798},[48,1205,698],{"mathvariant":1206},"normal",[227,1208,799],{"stretchy":798},[48,1210,15],{},[48,1212,90],{},[227,1214,811],{"stretchy":798},[227,1216,229],{},[227,1218,799],{"stretchy":798},[48,1220,1195],{},[227,1222,920],{},[48,1224,50],{},[227,1226,811],{"stretchy":798},[48,1228,698],{"mathvariant":1206},[48,1230,90],{},[52,1232,1233],{"encoding":54},"(ax - a\\mu)\u002F(a\\sigma) = (x-\\mu)\u002F\\sigma",[29,1235,1237,1262,1299,1320],{"className":1236,"ariaHidden":60},[59],[29,1238,1240,1244,1247,1250,1253,1256,1259],{"className":1239},[64],[29,1241],{"className":1242,"style":1243},[68],"height:1em;vertical-align:-0.25em;",[29,1245,799],{"className":1246},[832],[29,1248,15],{"className":1249},[73,74],[29,1251,1195],{"className":1252},[73,74],[29,1254],{"className":1255,"style":962},[307],[29,1257,920],{"className":1258},[966],[29,1260],{"className":1261,"style":962},[307],[29,1263,1265,1268,1271,1274,1277,1280,1283,1287,1290,1293,1296],{"className":1264},[64],[29,1266],{"className":1267,"style":1243},[68],[29,1269,15],{"className":1270},[73,74],[29,1272,50],{"className":1273},[73,74],[29,1275,811],{"className":1276},[867],[29,1278,698],{"className":1279},[73],[29,1281,799],{"className":1282},[832],[29,1284,1286],{"className":1285,"style":107},[73,74],"aσ",[29,1288,811],{"className":1289},[867],[29,1291],{"className":1292,"style":308},[307],[29,1294,229],{"className":1295},[312],[29,1297],{"className":1298,"style":308},[307],[29,1300,1302,1305,1308,1311,1314,1317],{"className":1301},[64],[29,1303],{"className":1304,"style":1243},[68],[29,1306,799],{"className":1307},[832],[29,1309,1195],{"className":1310},[73,74],[29,1312],{"className":1313,"style":962},[307],[29,1315,920],{"className":1316},[966],[29,1318],{"className":1319,"style":962},[307],[29,1321,1323,1326,1329,1332,1335],{"className":1322},[64],[29,1324],{"className":1325,"style":1243},[68],[29,1327,50],{"className":1328},[73,74],[29,1330,811],{"className":1331},[867],[29,1333,698],{"className":1334},[73],[29,1336,90],{"className":1337,"style":107},[73,74],". Esse é o argumento mais forte a favor de normalizar: o resultado deixa de depender de uma escolha arbitrária de unidade.",[877,1340,1342],{"id":1341},"exercício-2-min-max-vs-z-score","Exercício 2: min-max vs z-score",[11,1344,1345,1346,1396,1397,1427],{},"Normaliza com min-max em vez de z-score e roda o gradiente descendente com ",[29,1347,1349,1366],{"className":1348},[32],[29,1350,1352],{"className":1351},[36],[38,1353,1354],{"xmlns":40},[42,1355,1356,1364],{},[45,1357,1358,1360,1362],{},[48,1359,902],{},[227,1361,229],{},[231,1363,1034],{},[52,1365,1037],{"encoding":54},[29,1367,1369,1387],{"className":1368,"ariaHidden":60},[59],[29,1370,1372,1375,1378,1381,1384],{"className":1371},[64],[29,1373],{"className":1374,"style":103},[68],[29,1376,902],{"className":1377,"style":939},[73,74],[29,1379],{"className":1380,"style":308},[307],[29,1382,229],{"className":1383},[312],[29,1385],{"className":1386,"style":308},[307],[29,1388,1390,1393],{"className":1389},[64],[29,1391],{"className":1392,"style":322},[68],[29,1394,1034],{"className":1395},[73],", 1000 iterações. Compara o custo final e o ",[29,1398,1400,1415],{"className":1399},[32],[29,1401,1403],{"className":1402},[36],[38,1404,1405],{"xmlns":40},[42,1406,1407,1412],{},[45,1408,1409],{},[48,1410,1411],{},"κ",[52,1413,1414],{"encoding":54},"\\kappa",[29,1416,1418],{"className":1417,"ariaHidden":60},[59],[29,1419,1421,1424],{"className":1420},[64],[29,1422],{"className":1423,"style":103},[68],[29,1425,1411],{"className":1426},[73,74],". Depois insere um outlier (uma casa de 20000 pés²) e repete.",[1069,1429,1430,1434,1653],{},[1072,1431,1432],{},[650,1433,1076],{},[11,1435,1436,1437,635,1494,1522,1523,1594,1595,1623,1624,1652],{},"Sem outlier, min-max funciona quase tão bem quanto z-score (features em ",[29,1438,1440,1465],{"className":1439},[32],[29,1441,1443],{"className":1442},[36],[38,1444,1445],{"xmlns":40},[42,1446,1447,1462],{},[45,1448,1449,1452,1454,1457,1459],{},[227,1450,1451],{"stretchy":798},"[",[231,1453,233],{},[227,1455,1456],{"separator":60},",",[231,1458,979],{},[227,1460,1461],{"stretchy":798},"]",[52,1463,1464],{"encoding":54},"[0,1]",[29,1466,1468],{"className":1467,"ariaHidden":60},[59],[29,1469,1471,1474,1477,1480,1484,1488,1491],{"className":1470},[64],[29,1472],{"className":1473,"style":1243},[68],[29,1475,1451],{"className":1476},[832],[29,1478,233],{"className":1479},[73],[29,1481,1456],{"className":1482},[1483],"mpunct",[29,1485],{"className":1486,"style":1487},[307],"margin-right:0.1667em;",[29,1489,979],{"className":1490},[73],[29,1492,1461],{"className":1493},[867],[29,1495,1497,1510],{"className":1496},[32],[29,1498,1500],{"className":1499},[36],[38,1501,1502],{"xmlns":40},[42,1503,1504,1508],{},[45,1505,1506],{},[48,1507,1411],{},[52,1509,1414],{"encoding":54},[29,1511,1513],{"className":1512,"ariaHidden":60},[59],[29,1514,1516,1519],{"className":1515},[64],[29,1517],{"className":1518,"style":103},[68],[29,1520,1411],{"className":1521},[73,74]," bem menor que no dado cru). Mas repara que min-max não centraliza em zero, o que deixa uma correlação residual entre os ",[29,1524,1526,1544],{"className":1525},[32],[29,1527,1529],{"className":1528},[36],[38,1530,1531],{"xmlns":40},[42,1532,1533,1541],{},[45,1534,1535],{},[219,1536,1537,1539],{},[48,1538,595],{},[48,1540,225],{},[52,1542,1543],{"encoding":54},"w_j",[29,1545,1547],{"className":1546,"ariaHidden":60},[59],[29,1548,1550,1553],{"className":1549},[64],[29,1551],{"className":1552,"style":246},[68],[29,1554,1556,1559],{"className":1555},[73],[29,1557,595],{"className":1558,"style":616},[73,74],[29,1560,1562],{"className":1561},[256],[29,1563,1565,1586],{"className":1564},[260,261],[29,1566,1568,1583],{"className":1567},[265],[29,1569,1571],{"className":1570,"style":270},[269],[29,1572,1574,1577],{"style":1573},"top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;",[29,1575],{"className":1576,"style":278},[277],[29,1578,1580],{"className":1579},[282,283,284,285],[29,1581,225],{"className":1582,"style":289},[73,74,285],[29,1584,294],{"className":1585},[293],[29,1587,1589],{"className":1588},[265],[29,1590,1592],{"className":1591,"style":301},[269],[29,1593],{}," e o ",[29,1596,1598,1611],{"className":1597},[32],[29,1599,1601],{"className":1600},[36],[38,1602,1603],{"xmlns":40},[42,1604,1605,1609],{},[45,1606,1607],{},[48,1608,650],{},[52,1610,650],{"encoding":54},[29,1612,1614],{"className":1613,"ariaHidden":60},[59],[29,1615,1617,1620],{"className":1616},[64],[29,1618],{"className":1619,"style":668},[68],[29,1621,650],{"className":1622},[73,74],", e o ",[29,1625,1627,1640],{"className":1626},[32],[29,1628,1630],{"className":1629},[36],[38,1631,1632],{"xmlns":40},[42,1633,1634,1638],{},[45,1635,1636],{},[48,1637,1411],{},[52,1639,1414],{"encoding":54},[29,1641,1643],{"className":1642,"ariaHidden":60},[59],[29,1644,1646,1649],{"className":1645},[64],[29,1647],{"className":1648,"style":103},[68],[29,1650,1411],{"className":1651},[73,74]," costuma ficar pior que o do z-score.",[11,1654,1655,1656,1658,1659,1662],{},"Com o outlier, min-max colapsa: ",[120,1657,886],{}," vira quase 0 pra todas as casas normais e 1 só pro outlier, destruindo a resolução da feature pras casas de verdade. Z-score também sofre (média e desvio-padrão não são robustos a outlier), mas bem menos. Solução robusta de verdade: ",[120,1660,1661],{},"sklearn.preprocessing.RobustScaler"," (usa mediana e IQR em vez de média e desvio-padrão).",[877,1664,1666],{"id":1665},"exercício-3-implementa-o-critério-de-parada","Exercício 3: implementa o critério de parada",[11,1668,1669,1670,1673,1674,1677,1678,334],{},"Meu ",[120,1671,1672],{},"gradient_descent"," sempre roda ",[120,1675,1676],{},"num_iters"," iterações inteiras. Adiciona uma parada antecipada quando ",[29,1679,1681,1717],{"className":1680},[32],[29,1682,1684],{"className":1683},[36],[38,1685,1686],{"xmlns":40},[42,1687,1688,1714],{},[45,1689,1690,1693,1696,1699,1706,1709],{},[48,1691,1692],{"mathvariant":1206},"∥",[48,1694,1695],{"mathvariant":1206},"∇",[48,1697,1698],{},"J",[219,1700,1701,1703],{},[48,1702,1692],{"mathvariant":1206},[48,1704,1705],{"mathvariant":1206},"∞",[227,1707,1708],{},"\u003C",[1710,1711,1713],"mtext",{"mathvariant":1712},"monospace","tol",[52,1715,1716],{"encoding":54},"\\|\\nabla J\\|_\\infty \u003C \\texttt{tol}",[29,1718,1720,1786],{"className":1719,"ariaHidden":60},[59],[29,1721,1723,1726,1730,1734,1777,1780,1783],{"className":1722},[64],[29,1724],{"className":1725,"style":1243},[68],[29,1727,1729],{"className":1728},[73],"∥∇",[29,1731,1698],{"className":1732,"style":1733},[73,74],"margin-right:0.0962em;",[29,1735,1737,1740],{"className":1736},[73],[29,1738,1692],{"className":1739},[73],[29,1741,1743],{"className":1742},[256],[29,1744,1746,1768],{"className":1745},[260,261],[29,1747,1749,1765],{"className":1748},[265],[29,1750,1753],{"className":1751,"style":1752},[269],"height:0.1514em;",[29,1754,1756,1759],{"style":1755},"top:-2.55em;margin-left:0em;margin-right:0.05em;",[29,1757],{"className":1758,"style":278},[277],[29,1760,1762],{"className":1761},[282,283,284,285],[29,1763,1705],{"className":1764},[73,285],[29,1766,294],{"className":1767},[293],[29,1769,1771],{"className":1770},[265],[29,1772,1775],{"className":1773,"style":1774},[269],"height:0.15em;",[29,1776],{},[29,1778],{"className":1779,"style":308},[307],[29,1781,1708],{"className":1782},[312],[29,1784],{"className":1785,"style":308},[307],[29,1787,1789,1793],{"className":1788},[64],[29,1790],{"className":1791,"style":1792},[68],"height:0.6111em;",[29,1794,1797],{"className":1795},[73,1796],"text",[29,1798,1713],{"className":1799},[73,1800],"texttt",[1069,1802,1803,1807,1832],{},[1072,1804,1805],{},[650,1806,1076],{},[113,1808,1810],{"className":115,"code":1809,"language":117,"meta":118,"style":118},"grad_norm = max(np.max(np.abs(dj_dw)), abs(dj_db))\nif grad_norm \u003C tol:\n    print(f\"Convergiu na iteracao {i}: |grad|_inf = {grad_norm:.2e}\")\n    break\n",[120,1811,1812,1817,1822,1827],{"__ignoreMap":118},[29,1813,1814],{"class":124,"line":125},[29,1815,1816],{},"grad_norm = max(np.max(np.abs(dj_dw)), abs(dj_db))\n",[29,1818,1819],{"class":124,"line":131},[29,1820,1821],{},"if grad_norm \u003C tol:\n",[29,1823,1824],{"class":124,"line":376},[29,1825,1826],{},"    print(f\"Convergiu na iteracao {i}: |grad|_inf = {grad_norm:.2e}\")\n",[29,1828,1829],{"class":124,"line":382},[29,1830,1831],{},"    break\n",[11,1833,1834,1835,1838,1839,1867],{},"Um critério pela melhora do custo (",[120,1836,1837],{},"abs(J_ant - J_novo) \u002F max(abs(J_ant), 1e-12) \u003C tol",") também é comum, mas tem um risco: com ",[29,1840,1842,1855],{"className":1841},[32],[29,1843,1845],{"className":1844},[36],[38,1846,1847],{"xmlns":40},[42,1848,1849,1853],{},[45,1850,1851],{},[48,1852,902],{},[52,1854,1130],{"encoding":54},[29,1856,1858],{"className":1857,"ariaHidden":60},[59],[29,1859,1861,1864],{"className":1860},[64],[29,1862],{"className":1863,"style":103},[68],[29,1865,902],{"className":1866,"style":939},[73,74]," pequeno demais, o custo também melhora pouco por iteração, e o algoritmo para achando que convergiu sem ter convergido de verdade. O critério pelo gradiente é mais confiável.",[877,1869,1871,1872,1900],{"id":1870},"exercício-4-prevê-o-αalphaα-crítico","Exercício 4: prevê o ",[29,1873,1875,1888],{"className":1874},[32],[29,1876,1878],{"className":1877},[36],[38,1879,1880],{"xmlns":40},[42,1881,1882,1886],{},[45,1883,1884],{},[48,1885,902],{},[52,1887,1130],{"encoding":54},[29,1889,1891],{"className":1890,"ariaHidden":60},[59],[29,1892,1894,1897],{"className":1893},[64],[29,1895],{"className":1896,"style":103},[68],[29,1898,902],{"className":1899,"style":939},[73,74]," crítico",[11,1902,1903,1904,1932,1933,75,1968,2003],{},"Sem rodar o gradiente descendente, calcula o ",[29,1905,1907,1920],{"className":1906},[32],[29,1908,1910],{"className":1909},[36],[38,1911,1912],{"xmlns":40},[42,1913,1914,1918],{},[45,1915,1916],{},[48,1917,902],{},[52,1919,1130],{"encoding":54},[29,1921,1923],{"className":1922,"ariaHidden":60},[59],[29,1924,1926,1929],{"className":1925},[64],[29,1927],{"className":1928,"style":103},[68],[29,1930,902],{"className":1931,"style":939},[73,74]," crítico pros dados normalizados por min-max. Depois confirma empiricamente rodando com ",[29,1934,1936,1953],{"className":1935},[32],[29,1937,1939],{"className":1938},[36],[38,1940,1941],{"xmlns":40},[42,1942,1943,1950],{},[45,1944,1945,1948],{},[231,1946,1947],{},"0.9",[227,1949,910],{},[52,1951,1952],{"encoding":54},"0.9\\times",[29,1954,1956],{"className":1955,"ariaHidden":60},[59],[29,1957,1959,1962,1965],{"className":1958},[64],[29,1960],{"className":1961,"style":955},[68],[29,1963,1947],{"className":1964},[73],[29,1966,910],{"className":1967},[73],[29,1969,1971,1988],{"className":1970},[32],[29,1972,1974],{"className":1973},[36],[38,1975,1976],{"xmlns":40},[42,1977,1978,1985],{},[45,1979,1980,1983],{},[231,1981,1982],{},"1.1",[227,1984,910],{},[52,1986,1987],{"encoding":54},"1.1\\times",[29,1989,1991],{"className":1990,"ariaHidden":60},[59],[29,1992,1994,1997,2000],{"className":1993},[64],[29,1995],{"className":1996,"style":955},[68],[29,1998,1982],{"className":1999},[73],[29,2001,910],{"className":2002},[73]," esse valor.",[1069,2005,2006,2010,2030],{},[1072,2007,2008],{},[650,2009,1076],{},[113,2011,2013],{"className":115,"code":2012,"language":117,"meta":118,"style":118},"Xmm = minmax_scaling(X_train)\nHa = (np.column_stack([Xmm, np.ones(m)]).T @ np.column_stack([Xmm, np.ones(m)])) \u002F m\na_crit = 2 \u002F np.linalg.eigvalsh(Ha)[-1]\n",[120,2014,2015,2020,2025],{"__ignoreMap":118},[29,2016,2017],{"class":124,"line":125},[29,2018,2019],{},"Xmm = minmax_scaling(X_train)\n",[29,2021,2022],{"class":124,"line":131},[29,2023,2024],{},"Ha = (np.column_stack([Xmm, np.ones(m)]).T @ np.column_stack([Xmm, np.ones(m)])) \u002F m\n",[29,2026,2027],{"class":124,"line":376},[29,2028,2029],{},"a_crit = 2 \u002F np.linalg.eigvalsh(Ha)[-1]\n",[11,2031,2032,2033,2061,2062,2090],{},"Funciona porque ",[29,2034,2036,2049],{"className":2035},[32],[29,2037,2039],{"className":2038},[36],[38,2040,2041],{"xmlns":40},[42,2042,2043,2047],{},[45,2044,2045],{},[48,2046,1698],{},[52,2048,1698],{"encoding":54},[29,2050,2052],{"className":2051,"ariaHidden":60},[59],[29,2053,2055,2058],{"className":2054},[64],[29,2056],{"className":2057,"style":1109},[68],[29,2059,1698],{"className":2060,"style":1733},[73,74]," é exatamente quadrática, o que faz a Hessiana ser constante em qualquer ponto. Pra modelos não lineares (rede neural) a curvatura ",[29,2063,2065,2078],{"className":2064},[32],[29,2066,2068],{"className":2067},[36],[38,2069,2070],{"xmlns":40},[42,2071,2072,2076],{},[45,2073,2074],{},[48,2075,1097],{},[52,2077,1097],{"encoding":54},[29,2079,2081],{"className":2080,"ariaHidden":60},[59],[29,2082,2084,2087],{"className":2083},[64],[29,2085],{"className":2086,"style":1109},[68],[29,2088,1097],{"className":2089},[73,74]," muda a cada ponto, e essa conta só vale localmente, é exatamente por isso que existem otimizadores adaptativos como Adam.",[877,2092,2094],{"id":2093},"exercício-5-feature-nova","Exercício 5: feature nova",[11,2096,2097,2098,2101],{},"Adiciona a feature ",[120,2099,2100],{},"tamanho_por_quarto = size \u002F bedrooms",", normaliza e treina. O erro melhora?",[1069,2103,2104,2108],{},[1072,2105,2106],{},[650,2107,1076],{},[11,2109,2110,2111,2115,2116,186,2119,2147,2148,2151,2152,2155],{},"Engenharia de features é ",[15,2112,2114],{"href":2113},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab04-feature-engineering","o tema do próximo lab",". O ponto de atenção aqui: features derivadas costumam ficar fortemente correlacionadas com as originais, o que ",[141,2117,2118],{},"aumenta",[29,2120,2122,2135],{"className":2121},[32],[29,2123,2125],{"className":2124},[36],[38,2126,2127],{"xmlns":40},[42,2128,2129,2133],{},[45,2130,2131],{},[48,2132,1411],{},[52,2134,1414],{"encoding":54},[29,2136,2138],{"className":2137,"ariaHidden":60},[59],[29,2139,2141,2144],{"className":2140},[64],[29,2142],{"className":2143,"style":103},[68],[29,2145,1411],{"className":2146},[73,74]," e pode deixar a convergência mais lenta mesmo depois de normalizar. Normalização resolve diferença de ",[141,2149,2150],{},"escala",", não resolve ",[141,2153,2154],{},"colinearidade",", pra isso existem regularização (Ridge) e PCA.",[2157,2158,2159],"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":118,"searchDepth":131,"depth":131,"links":2161},[2162,2163,2164,2165,2166],{"id":23,"depth":131,"text":24},{"id":201,"depth":131,"text":202},{"id":446,"depth":131,"text":447},{"id":555,"depth":131,"text":556},{"id":871,"depth":131,"text":872,"children":2167},[2168,2169,2170,2171,2173],{"id":879,"depth":376,"text":880},{"id":1341,"depth":376,"text":1342},{"id":1665,"depth":376,"text":1666},{"id":1870,"depth":376,"text":2172},"Exercício 4: prevê o α\\alphaα crítico",{"id":2093,"depth":376,"text":2094},null,"2026-08-19","Vazamento de dado, feature constante, quando não normalizar e como eu conferi minha implementação com uma solução exata. As armadilhas que só aparecem quando o modelo sai do notebook e vai pra produção.","md",{},"\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Ffeature-scaling-pitfalls","machine-learning-specialization",{"title":6,"description":2176},"draft","pt\u002Fplaylists\u002Fmachine-learning-specialization\u002Ffeature-scaling-pitfalls",[2185,2186,2187],"normalizacao","data-leakage","scikit-learn","rFrHSZ97Pss9aRGoiCQhBJmo_cW_LLMUUROLkV3V10g",1787338985131]