[{"data":1,"prerenderedAt":1900},["ShallowReactive",2],{"lang-switch-post-\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization":3,"post-pt-machine-learning-specialization-w2-lab01-numpy-vectorization":4},"\u002Fen\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization",{"id":5,"title":6,"body":7,"cover":1885,"date":1886,"description":1887,"extension":1888,"meta":1889,"navigation":326,"order":336,"path":1890,"playlist":1891,"seo":1892,"status":1893,"stem":1894,"tags":1895,"__hash__":1899},"posts\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization.md","NumPy e Vetorização",{"type":8,"value":9,"toc":1871},"minimark",[10,18,26,31,39,48,51,55,305,369,376,381,403,442,446,452,486,498,504,508,531,825,828,887,891,901,907,920,931,934,937,941,1034,1068,1094,1344,1348,1570,1588,1592,1607,1658,1677,1711,1726,1769,1773,1864,1867],[11,12,13],"p",{},[14,15],"img",{"alt":16,"src":17},"Meme \"o protetor silencioso\": um soldado rotulado como Álgebra Linear, Estatística, Cálculo e Teoria da Probabilidade toma tiro atrás de tiro no lugar de um \"ML Newbie\" que dorme tranquilo numa cama, sem fazer ideia de nada disso","\u002Fimages\u002Fposts\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization\u002Fmeme-vectorization.jpg",[11,19,20,21,25],{},"Bora fazer uma pausa na trilogia. Esse post não tem modelo novo pra treinar, não tem custo pra calcular, não tem ladeira pra descer. É um post de ferramenta, tipo parar no posto pra trocar o pneu carequinha antes dele estourar na estrada. Ele existe porque a partir da Semana 2 do curso o modelo ganha várias features de uma vez (tamanho, número de quartos, idade da casa, tudo junto), e a essa altura fazer conta com laço ",[22,23,24],"code",{},"for"," deixa de ser viável. Bora entender a ferramenta que resolve isso antes de precisar dela de verdade.",[27,28,30],"h2",{"id":29},"lista-python-funciona-então-por-que-trocar","Lista Python funciona, então por que trocar",[11,32,33,34,38],{},"Python já vem com listas, que guardam número igual a array. Então por que a comunidade inteira de ML usa uma biblioteca à parte pra isso? Resposta curta: ",[35,36,37],"strong",{},"memória",".",[11,40,41,42,47],{},"Uma lista Python guarda cada número como um objeto separado, espalhado pela memória, com um monte de informação extra grudada nele (tipo, contador de referência, etc). Fazer conta em cima disso significa o processador ficar pulando de endereço em endereço, desembrulhando cada objeto pra pegar o valor de dentro. Já um array ",[43,44,46],"glossary-term",{"definition":45},"biblioteca de Python especializada em arrays numéricos, com todos os elementos do mesmo tipo guardados lado a lado na memória","NumPy"," guarda os números crus, do mesmo tipo, um do lado do outro, num bloco contínuo de memória. O processador consegue processar um monte deles de uma vez, com instruções especiais que existem exatamente pra isso.",[11,49,50],{},"Essa diferença de layout de memória é o motivo de verdade por trás da velocidade do NumPy. Não é mágica, é engenharia de baixo nível.",[27,52,54],{"id":53},"vetor-a-peça-básica","Vetor: a peça básica",[11,56,57,58,106,107,111,112,172,173,202,203,249,250,304],{},"Um vetor é um monte de números organizados em ordem, com todos do mesmo tipo. Na notação do curso, vetor é letra minúscula em negrito, tipo ",[59,60,63,87],"span",{"className":61},[62],"katex",[59,64,67],{"className":65},[66],"katex-mathml",[68,69,71],"math",{"xmlns":70},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML",[72,73,74,82],"semantics",{},[75,76,77],"mrow",{},[78,79,81],"mi",{"mathvariant":80},"bold","x",[83,84,86],"annotation",{"encoding":85},"application\u002Fx-tex","\\mathbf{x}",[59,88,92],{"className":89,"ariaHidden":91},[90],"katex-html","true",[59,93,96,101],{"className":94},[95],"base",[59,97],{"className":98,"style":100},[99],"strut","height:0.4444em;",[59,102,81],{"className":103},[104,105],"mord","mathbf",". O tamanho de um vetor chama ",[43,108,110],{"definition":109},"uma tupla que descreve o formato de um array: quantos elementos em cada dimensão","shape",", escrito ",[59,113,115,141],{"className":114},[62],[59,116,118],{"className":117},[66],[68,119,120],{"xmlns":70},[72,121,122,138],{},[75,123,124,129,132,135],{},[125,126,128],"mo",{"stretchy":127},"false","(",[78,130,131],{},"n",[125,133,134],{"separator":91},",",[125,136,137],{"stretchy":127},")",[83,139,140],{"encoding":85},"(n,)",[59,142,144],{"className":143,"ariaHidden":91},[90],[59,145,147,151,155,159,163,168],{"className":146},[95],[59,148],{"className":149,"style":150},[99],"height:1em;vertical-align:-0.25em;",[59,152,128],{"className":153},[154],"mopen",[59,156,131],{"className":157},[104,158],"mathnormal",[59,160,134],{"className":161},[162],"mpunct",[59,164],{"className":165,"style":167},[166],"mspace","margin-right:0.1667em;",[59,169,137],{"className":170},[171],"mclose"," pra um vetor de ",[59,174,176,189],{"className":175},[62],[59,177,179],{"className":178},[66],[68,180,181],{"xmlns":70},[72,182,183,187],{},[75,184,185],{},[78,186,131],{},[83,188,131],{"encoding":85},[59,190,192],{"className":191,"ariaHidden":91},[90],[59,193,195,199],{"className":194},[95],[59,196],{"className":197,"style":198},[99],"height:0.4306em;",[59,200,131],{"className":201},[104,158]," elementos. Repara na vírgula sozinha ali dentro dos parênteses: ela é o jeito do Python dizer \"isso é uma tupla de um elemento só\", e é fácil confundir ",[59,204,206,225],{"className":205},[62],[59,207,209],{"className":208},[66],[68,210,211],{"xmlns":70},[72,212,213,223],{},[75,214,215,217,219,221],{},[125,216,128],{"stretchy":127},[78,218,131],{},[125,220,134],{"separator":91},[125,222,137],{"stretchy":127},[83,224,140],{"encoding":85},[59,226,228],{"className":227,"ariaHidden":91},[90],[59,229,231,234,237,240,243,246],{"className":230},[95],[59,232],{"className":233,"style":150},[99],[59,235,128],{"className":236},[154],[59,238,131],{"className":239},[104,158],[59,241,134],{"className":242},[162],[59,244],{"className":245,"style":167},[166],[59,247,137],{"className":248},[171]," com ",[59,251,253,277],{"className":252},[62],[59,254,256],{"className":255},[66],[68,257,258],{"xmlns":70},[72,259,260,274],{},[75,261,262,264,266,268,272],{},[125,263,128],{"stretchy":127},[78,265,131],{},[125,267,134],{"separator":91},[269,270,271],"mn",{},"1",[125,273,137],{"stretchy":127},[83,275,276],{"encoding":85},"(n,1)",[59,278,280],{"className":279,"ariaHidden":91},[90],[59,281,283,286,289,292,295,298,301],{"className":282},[95],[59,284],{"className":285,"style":150},[99],[59,287,128],{"className":288},[154],[59,290,131],{"className":291},[104,158],[59,293,134],{"className":294},[162],[59,296],{"className":297,"style":167},[166],[59,299,271],{"className":300},[104],[59,302,137],{"className":303},[171]," mais pra frente, então já fica de olho nisso.",[306,307,312],"pre",{"className":308,"code":309,"language":310,"meta":311,"style":311},"language-python shiki shiki-themes github-light github-dark","import numpy as np\n\na = np.zeros(4)\nprint(f\"np.zeros(4): a = {a}, shape = {a.shape}, dtype = {a.dtype}\")\n# a = [0. 0. 0. 0.], shape = (4,), dtype = float64\n\na = np.array([5, 4, 3, 2])\nprint(f\"np.array: a = {a}, shape = {a.shape}, dtype = {a.dtype}\")\n# a = [5 4 3 2], shape = (4,), dtype = int64\n","python","",[22,313,314,321,328,334,340,346,351,357,363],{"__ignoreMap":311},[59,315,318],{"class":316,"line":317},"line",1,[59,319,320],{},"import numpy as np\n",[59,322,324],{"class":316,"line":323},2,[59,325,327],{"emptyLinePlaceholder":326},true,"\n",[59,329,331],{"class":316,"line":330},3,[59,332,333],{},"a = np.zeros(4)\n",[59,335,337],{"class":316,"line":336},4,[59,338,339],{},"print(f\"np.zeros(4): a = {a}, shape = {a.shape}, dtype = {a.dtype}\")\n",[59,341,343],{"class":316,"line":342},5,[59,344,345],{},"# a = [0. 0. 0. 0.], shape = (4,), dtype = float64\n",[59,347,349],{"class":316,"line":348},6,[59,350,327],{"emptyLinePlaceholder":326},[59,352,354],{"class":316,"line":353},7,[59,355,356],{},"a = np.array([5, 4, 3, 2])\n",[59,358,360],{"class":316,"line":359},8,[59,361,362],{},"print(f\"np.array: a = {a}, shape = {a.shape}, dtype = {a.dtype}\")\n",[59,364,366],{"class":316,"line":365},9,[59,367,368],{},"# a = [5 4 3 2], shape = (4,), dtype = int64\n",[11,370,371,372,375],{},"Um detalhe que me pegou de primeira viagem: um único valor com ponto decimal na lista já é suficiente pra o array inteiro virar ",[22,373,374],{},"float64",". Faz sentido, já que todo elemento do array precisa ser do mesmo tipo.",[377,378,380],"h3",{"id":379},"indexação-e-fatiamento","Indexação e fatiamento",[11,382,383,384,387,388,391,392,395,396,399,400,402],{},"Indexar (",[22,385,386],{},"a[2]",") pega um elemento, enquanto fatiar (",[22,389,390],{},"a[2:7]",") pega um pedaço. As regras são as mesmas que listas Python: conta começa em zero, índice negativo conta do fim (",[22,393,394],{},"a[-1]"," é o último elemento), e o fim do fatiamento ",[35,397,398],{},"não"," entra (",[22,401,390],{}," pega os índices 2, 3, 4, 5 e 6, cinco elementos, não seis).",[306,404,406],{"className":308,"code":405,"language":310,"meta":311,"style":311},"a = np.arange(10)          # [0 1 2 3 4 5 6 7 8 9]\n\nprint(a[2])                 # 2, um elemento pego = um escalar\nprint(a[-1])                 # 9, último elemento\nprint(a[2:7:1])              # [2 3 4 5 6], do índice 2 até o 6\nprint(a[3:])                  # [3 4 5 6 7 8 9], do índice 3 até o fim\nprint(a[:3])                   # [0 1 2], do início até o índice 2\n",[22,407,408,413,417,422,427,432,437],{"__ignoreMap":311},[59,409,410],{"class":316,"line":317},[59,411,412],{},"a = np.arange(10)          # [0 1 2 3 4 5 6 7 8 9]\n",[59,414,415],{"class":316,"line":323},[59,416,327],{"emptyLinePlaceholder":326},[59,418,419],{"class":316,"line":330},[59,420,421],{},"print(a[2])                 # 2, um elemento pego = um escalar\n",[59,423,424],{"class":316,"line":336},[59,425,426],{},"print(a[-1])                 # 9, último elemento\n",[59,428,429],{"class":316,"line":342},[59,430,431],{},"print(a[2:7:1])              # [2 3 4 5 6], do índice 2 até o 6\n",[59,433,434],{"class":316,"line":348},[59,435,436],{},"print(a[3:])                  # [3 4 5 6 7 8 9], do índice 3 até o fim\n",[59,438,439],{"class":316,"line":353},[59,440,441],{},"print(a[:3])                   # [0 1 2], do início até o índice 2\n",[377,443,445],{"id":444},"operações-sem-laço-nenhum","Operações sem laço nenhum",[11,447,448,449,451],{},"Aqui mora a parte boa. Operações de vetor rodam em cima do array inteiro de uma vez, sem você escrever nenhum ",[22,450,24],{},":",[306,453,455],{"className":308,"code":454,"language":310,"meta":311,"style":311},"a = np.array([1, 2, 3, 4])\n\nprint(-a)          # [-1 -2 -3 -4], troca o sinal de todo mundo de uma vez\nprint(np.sum(a))   # 10, soma tudo\nprint(a ** 2)       # [1 4 9 16], eleva cada elemento ao quadrado\nprint(5 * a)          # [5 10 15 20], multiplica cada elemento por 5\n",[22,456,457,462,466,471,476,481],{"__ignoreMap":311},[59,458,459],{"class":316,"line":317},[59,460,461],{},"a = np.array([1, 2, 3, 4])\n",[59,463,464],{"class":316,"line":323},[59,465,327],{"emptyLinePlaceholder":326},[59,467,468],{"class":316,"line":330},[59,469,470],{},"print(-a)          # [-1 -2 -3 -4], troca o sinal de todo mundo de uma vez\n",[59,472,473],{"class":316,"line":336},[59,474,475],{},"print(np.sum(a))   # 10, soma tudo\n",[59,477,478],{"class":316,"line":342},[59,479,480],{},"print(a ** 2)       # [1 4 9 16], eleva cada elemento ao quadrado\n",[59,482,483],{"class":316,"line":348},[59,484,485],{},"print(5 * a)          # [5 10 15 20], multiplica cada elemento por 5\n",[11,487,488,489,492,493,497],{},"Repara no último exemplo: o ",[22,490,491],{},"5"," era só um número solto, mas o NumPy \"esticou\" ele sozinho pra combinar com os 4 elementos do array. Isso tem nome, ",[43,494,496],{"definition":495},"quando o NumPy estica um número (ou um array menor) pra combinar com o tamanho de um array maior, sem você escrever loop nenhum","broadcasting",", e vai aparecer bastante daqui pra frente.",[11,499,500,501,503],{},"Isso é a ideia central desse lab inteiro: você descreve a operação sobre o array inteiro, e deixa o NumPy decidir como aplicar em cada elemento por baixo do capô. Se você reparar que tá escrevendo um ",[22,502,24],{}," pra percorrer um array, provavelmente existe uma versão vetorizada equivalente esperando pra ser usada.",[27,505,507],{"id":506},"produto-escalar-a-operação-que-sustenta-a-regressão-linear","Produto escalar: a operação que sustenta a regressão linear",[11,509,510,511,515,516,520,521,524,525,530],{},"O ",[43,512,514],{"definition":513},"multiplicar dois vetores elemento a elemento e somar tudo, resultando em um único número","produto escalar"," (",[517,518,519],"em",{},"dot product",") é a operação mais importante desse lab, porque é literalmente o que vai substituir aquele ",[22,522,523],{},"w * x[i] + b"," que a gente escreveu com laço ",[526,527,529],"a",{"href":528},"\u002Fplaylists\u002Fmachine-learning-specialization\u002Flab02-model-representation","nos posts anteriores",", quando o modelo ganhar várias features.",[11,532,533],{},[59,534,536,597],{"className":535},[62],[59,537,539],{"className":538},[66],[68,540,541],{"xmlns":70},[72,542,543,594],{},[75,544,545,547,550,553,556,581,588],{},[78,546,526],{"mathvariant":80},[125,548,549],{},"⋅",[78,551,552],{"mathvariant":80},"b",[125,554,555],{},"=",[557,558,559,562,572],"msubsup",{},[125,560,561],{},"∑",[75,563,564,567,569],{},[78,565,566],{},"i",[125,568,555],{},[269,570,571],{},"0",[75,573,574,576,579],{},[78,575,131],{},[125,577,578],{},"−",[269,580,271],{},[582,583,584,586],"msub",{},[78,585,526],{},[78,587,566],{},[582,589,590,592],{},[78,591,552],{},[78,593,566],{},[83,595,596],{"encoding":85},"\\mathbf{a} \\cdot \\mathbf{b} = \\sum_{i=0}^{n-1} a_i b_i",[59,598,600,621,642],{"className":599,"ariaHidden":91},[90],[59,601,603,607,610,614,618],{"className":602},[95],[59,604],{"className":605,"style":606},[99],"height:0.4445em;",[59,608,526],{"className":609},[104,105],[59,611],{"className":612,"style":613},[166],"margin-right:0.2222em;",[59,615,549],{"className":616},[617],"mbin",[59,619],{"className":620,"style":613},[166],[59,622,624,628,631,635,639],{"className":623},[95],[59,625],{"className":626,"style":627},[99],"height:0.6944em;",[59,629,552],{"className":630},[104,105],[59,632],{"className":633,"style":634},[166],"margin-right:0.2778em;",[59,636,555],{"className":637},[638],"mrel",[59,640],{"className":641,"style":634},[166],[59,643,645,649,739,742,785],{"className":644},[95],[59,646],{"className":647,"style":648},[99],"height:1.2537em;vertical-align:-0.2997em;",[59,650,653,659],{"className":651},[652],"mop",[59,654,561],{"className":655,"style":658},[652,656,657],"op-symbol","small-op","position:relative;top:0em;",[59,660,663],{"className":661},[662],"msupsub",[59,664,668,730],{"className":665},[666,667],"vlist-t","vlist-t2",[59,669,672,725],{"className":670},[671],"vlist-r",[59,673,677,704],{"className":674,"style":676},[675],"vlist","height:0.954em;",[59,678,680,685],{"style":679},"top:-2.4003em;margin-left:0em;margin-right:0.05em;",[59,681],{"className":682,"style":684},[683],"pstrut","height:2.7em;",[59,686,692],{"className":687},[688,689,690,691],"sizing","reset-size6","size3","mtight",[59,693,695,698,701],{"className":694},[104,691],[59,696,566],{"className":697},[104,158,691],[59,699,555],{"className":700},[638,691],[59,702,571],{"className":703},[104,691],[59,705,707,710],{"style":706},"top:-3.2029em;margin-right:0.05em;",[59,708],{"className":709,"style":684},[683],[59,711,713],{"className":712},[688,689,690,691],[59,714,716,719,722],{"className":715},[104,691],[59,717,131],{"className":718},[104,158,691],[59,720,578],{"className":721},[617,691],[59,723,271],{"className":724},[104,691],[59,726,729],{"className":727},[728],"vlist-s","​",[59,731,733],{"className":732},[671],[59,734,737],{"className":735,"style":736},[675],"height:0.2997em;",[59,738],{},[59,740],{"className":741,"style":167},[166],[59,743,745,748],{"className":744},[104],[59,746,526],{"className":747},[104,158],[59,749,751],{"className":750},[662],[59,752,754,776],{"className":753},[666,667],[59,755,757,773],{"className":756},[671],[59,758,761],{"className":759,"style":760},[675],"height:0.3117em;",[59,762,764,767],{"style":763},"top:-2.55em;margin-left:0em;margin-right:0.05em;",[59,765],{"className":766,"style":684},[683],[59,768,770],{"className":769},[688,689,690,691],[59,771,566],{"className":772},[104,158,691],[59,774,729],{"className":775},[728],[59,777,779],{"className":778},[671],[59,780,783],{"className":781,"style":782},[675],"height:0.15em;",[59,784],{},[59,786,788,791],{"className":787},[104],[59,789,552],{"className":790},[104,158],[59,792,794],{"className":793},[662],[59,795,797,817],{"className":796},[666,667],[59,798,800,814],{"className":799},[671],[59,801,803],{"className":802,"style":760},[675],[59,804,805,808],{"style":763},[59,806],{"className":807,"style":684},[683],[59,809,811],{"className":810},[688,689,690,691],[59,812,566],{"className":813},[104,158,691],[59,815,729],{"className":816},[728],[59,818,820],{"className":819},[671],[59,821,823],{"className":822,"style":782},[675],[59,824],{},[11,826,827],{},"Multiplica par a par, soma tudo. Simples assim. Antes de usar a versão pronta do NumPy, escrevi a minha, só pra deixar claro o que tá rolando por dentro:",[306,829,831],{"className":308,"code":830,"language":310,"meta":311,"style":311},"def my_dot(a, b):\n    x = 0\n    for i in range(a.shape[0]):\n        x = x + a[i] * b[i]\n    return x\n\na = np.array([1, 2, 3, 4])\nb = np.array([-1, 4, 3, 2])\n\nprint(my_dot(a, b))       # 24\nprint(np.dot(a, b))       # 24, mesmo resultado, função pronta do NumPy\n",[22,832,833,838,843,848,853,858,862,866,871,875,881],{"__ignoreMap":311},[59,834,835],{"class":316,"line":317},[59,836,837],{},"def my_dot(a, b):\n",[59,839,840],{"class":316,"line":323},[59,841,842],{},"    x = 0\n",[59,844,845],{"class":316,"line":330},[59,846,847],{},"    for i in range(a.shape[0]):\n",[59,849,850],{"class":316,"line":336},[59,851,852],{},"        x = x + a[i] * b[i]\n",[59,854,855],{"class":316,"line":342},[59,856,857],{},"    return x\n",[59,859,860],{"class":316,"line":348},[59,861,327],{"emptyLinePlaceholder":326},[59,863,864],{"class":316,"line":353},[59,865,461],{},[59,867,868],{"class":316,"line":359},[59,869,870],{},"b = np.array([-1, 4, 3, 2])\n",[59,872,873],{"class":316,"line":365},[59,874,327],{"emptyLinePlaceholder":326},[59,876,878],{"class":316,"line":877},10,[59,879,880],{},"print(my_dot(a, b))       # 24\n",[59,882,884],{"class":316,"line":883},11,[59,885,886],{},"print(np.dot(a, b))       # 24, mesmo resultado, função pronta do NumPy\n",[27,888,890],{"id":889},"a-diferença-de-velocidade-ao-vivo-no-seu-navegador","A diferença de velocidade, ao vivo no seu navegador",[11,892,893,894,897,898,900],{},"O notebook original testa isso com arrays de 10 milhões de elementos, comparando ",[22,895,896],{},"np.dot"," (vetorizado) contra um laço ",[22,899,24],{}," escrito à mão, em Python. O ganho lá é de dezenas a centenas de vezes.",[11,902,903,904,906],{},"Aqui embaixo você pode rodar um teste parecido, só que no seu próprio navegador, agora, com JavaScript. Só que preciso ser honesto com você sobre uma coisa antes: o navegador ",[35,905,398],{}," vai mostrar um ganho de 100 vezes. E não é porque o teste tá quebrado.",[11,908,909,910,912,913,916,917,919],{},"O motor JavaScript do seu navegador (o V8, se você usa Chrome ou Edge) já otimiza um laço ",[22,911,24],{}," simples de um jeito bem parecido com o que ele faz pra métodos prontos tipo ",[22,914,915],{},".reduce()",". Quando eu comparei \"laço\" contra \"",[22,918,915],{},"\" no mesmo tipo de array, deu um empate quase técnico, e isso era esperado, não bug do teste.",[11,921,922,923,926,927,930],{},"A comparação que de fato mostra uma diferença real e honesta é outra: ",[22,924,925],{},"Array"," comum do JavaScript (que guarda os números meio \"embrulhados\", parecido com a lista Python que a gente comentou lá em cima) contra ",[22,928,929],{},"Float64Array"," (memória contígua, tipo único, sem embrulho). Essa é a mesma razão de fundo que faz o NumPy ser rápido, só que reproduzida aqui no navegador com um ganho menor e honesto (geralmente de 2 a 5 vezes, às vezes mais), em vez de eu fingir que dava pra recriar o número gigante do Python num ambiente que não foi desenhado pra isso.",[932,933],"vectorization-benchmark",{},[11,935,936],{},"Roda algumas vezes com tamanhos diferentes. Repara que \"Array comum + laço\" costuma ser visivelmente mais lento que as outras duas, e que \"Float64Array + laço\" e \"Float64Array + .reduce()\" ficam bem próximos entre si. É exatamente esse padrão que a explicação acima previu.",[27,938,940],{"id":939},"matrizes-quando-um-vetor-não-basta","Matrizes: quando um vetor não basta",[11,942,943,944,975,976,1029,1030,1033],{},"Matriz é um array de duas dimensões, escrito com letra maiúscula em negrito (",[59,945,947,962],{"className":946},[62],[59,948,950],{"className":949},[66],[68,951,952],{"xmlns":70},[72,953,954,959],{},[75,955,956],{},[78,957,958],{"mathvariant":80},"X",[83,960,961],{"encoding":85},"\\mathbf{X}",[59,963,965],{"className":964,"ariaHidden":91},[90],[59,966,968,972],{"className":967},[95],[59,969],{"className":970,"style":971},[99],"height:0.6861em;",[59,973,958],{"className":974},[104,105],"), com shape ",[59,977,979,1002],{"className":978},[62],[59,980,982],{"className":981},[66],[68,983,984],{"xmlns":70},[72,985,986,999],{},[75,987,988,990,993,995,997],{},[125,989,128],{"stretchy":127},[78,991,992],{},"m",[125,994,134],{"separator":91},[78,996,131],{},[125,998,137],{"stretchy":127},[83,1000,1001],{"encoding":85},"(m, n)",[59,1003,1005],{"className":1004,"ariaHidden":91},[90],[59,1006,1008,1011,1014,1017,1020,1023,1026],{"className":1007},[95],[59,1009],{"className":1010,"style":150},[99],[59,1012,128],{"className":1013},[154],[59,1015,992],{"className":1016},[104,158],[59,1018,134],{"className":1019},[162],[59,1021],{"className":1022,"style":167},[166],[59,1024,131],{"className":1025},[104,158],[59,1027,137],{"className":1028},[171],". No contexto do curso a convenção é sempre a mesma: ",[35,1031,1032],{},"linha é exemplo de treino, coluna é feature",". Uma casa por linha, um atributo (tamanho, quartos, idade) por coluna.",[306,1035,1037],{"className":308,"code":1036,"language":310,"meta":311,"style":311},"X = np.array([[1, 5], [2, 3], [3, 1]])   # shape (3, 2): 3 exemplos, 2 features cada\n\nprint(X.shape)      # (3, 2)\nprint(X[1])          # [2 3], a linha 1 inteira, vira um vetor 1-D\nprint(X[1, 0])         # 2, um elemento específico, vira escalar\nprint(X[:, 0])           # [1 2 3], a coluna 0 inteira\n",[22,1038,1039,1044,1048,1053,1058,1063],{"__ignoreMap":311},[59,1040,1041],{"class":316,"line":317},[59,1042,1043],{},"X = np.array([[1, 5], [2, 3], [3, 1]])   # shape (3, 2): 3 exemplos, 2 features cada\n",[59,1045,1046],{"class":316,"line":323},[59,1047,327],{"emptyLinePlaceholder":326},[59,1049,1050],{"class":316,"line":330},[59,1051,1052],{},"print(X.shape)      # (3, 2)\n",[59,1054,1055],{"class":316,"line":336},[59,1056,1057],{},"print(X[1])          # [2 3], a linha 1 inteira, vira um vetor 1-D\n",[59,1059,1060],{"class":316,"line":342},[59,1061,1062],{},"print(X[1, 0])         # 2, um elemento específico, vira escalar\n",[59,1064,1065],{"class":316,"line":348},[59,1066,1067],{},"print(X[:, 0])           # [1 2 3], a coluna 0 inteira\n",[11,1069,1070,1071,1074,1075,1078,1079,1082,1083,1085,1086,1089,1090,1093],{},"O detalhe que mais confunde gente nova aqui: indexar uma matriz com ",[35,1072,1073],{},"um"," índice só (",[22,1076,1077],{},"X[1]",") devolve um array com ",[35,1080,1081],{},"uma dimensão a menos",", não uma matriz de uma linha só. ",[22,1084,1077],{}," tem shape ",[22,1087,1088],{},"(2,)",", não ",[22,1091,1092],{},"(1, 2)",". Essa pegadinha específica é a origem de boa parte dos erros de dimensão que você vai encontrar daqui pra frente no curso, e eu aprendi a grifar isso mentalmente sempre que mexo com shape.",[11,1095,1096,1097,1125,1126,1154,1155,1201,1202,1233,1234,1280,1281,1310,1311,1314,1315,1343],{},"E é justamente por causa disso que o produto escalar entra em cena de novo: quando o modelo tiver ",[59,1098,1100,1113],{"className":1099},[62],[59,1101,1103],{"className":1102},[66],[68,1104,1105],{"xmlns":70},[72,1106,1107,1111],{},[75,1108,1109],{},[78,1110,131],{},[83,1112,131],{"encoding":85},[59,1114,1116],{"className":1115,"ariaHidden":91},[90],[59,1117,1119,1122],{"className":1118},[95],[59,1120],{"className":1121,"style":198},[99],[59,1123,131],{"className":1124},[104,158]," features, cada linha da matriz ",[59,1127,1129,1142],{"className":1128},[62],[59,1130,1132],{"className":1131},[66],[68,1133,1134],{"xmlns":70},[72,1135,1136,1140],{},[75,1137,1138],{},[78,1139,958],{"mathvariant":80},[83,1141,961],{"encoding":85},[59,1143,1145],{"className":1144,"ariaHidden":91},[90],[59,1146,1148,1151],{"className":1147},[95],[59,1149],{"className":1150,"style":971},[99],[59,1152,958],{"className":1153},[104,105]," vira um vetor de shape ",[59,1156,1158,1177],{"className":1157},[62],[59,1159,1161],{"className":1160},[66],[68,1162,1163],{"xmlns":70},[72,1164,1165,1175],{},[75,1166,1167,1169,1171,1173],{},[125,1168,128],{"stretchy":127},[78,1170,131],{},[125,1172,134],{"separator":91},[125,1174,137],{"stretchy":127},[83,1176,140],{"encoding":85},[59,1178,1180],{"className":1179,"ariaHidden":91},[90],[59,1181,1183,1186,1189,1192,1195,1198],{"className":1182},[95],[59,1184],{"className":1185,"style":150},[99],[59,1187,128],{"className":1188},[154],[59,1190,131],{"className":1191},[104,158],[59,1193,134],{"className":1194},[162],[59,1196],{"className":1197,"style":167},[166],[59,1199,137],{"className":1200},[171],", pronto pra fazer produto escalar direto com o vetor de pesos ",[59,1203,1205,1220],{"className":1204},[62],[59,1206,1208],{"className":1207},[66],[68,1209,1210],{"xmlns":70},[72,1211,1212,1217],{},[75,1213,1214],{},[78,1215,1216],{"mathvariant":80},"w",[83,1218,1219],{"encoding":85},"\\mathbf{w}",[59,1221,1223],{"className":1222,"ariaHidden":91},[90],[59,1224,1226,1229],{"className":1225},[95],[59,1227],{"className":1228,"style":100},[99],[59,1230,1216],{"className":1231,"style":1232},[104,105],"margin-right:0.016em;",", também de shape ",[59,1235,1237,1256],{"className":1236},[62],[59,1238,1240],{"className":1239},[66],[68,1241,1242],{"xmlns":70},[72,1243,1244,1254],{},[75,1245,1246,1248,1250,1252],{},[125,1247,128],{"stretchy":127},[78,1249,131],{},[125,1251,134],{"separator":91},[125,1253,137],{"stretchy":127},[83,1255,140],{"encoding":85},[59,1257,1259],{"className":1258,"ariaHidden":91},[90],[59,1260,1262,1265,1268,1271,1274,1277],{"className":1261},[95],[59,1263],{"className":1264,"style":150},[99],[59,1266,128],{"className":1267},[154],[59,1269,131],{"className":1270},[104,158],[59,1272,134],{"className":1273},[162],[59,1275],{"className":1276,"style":167},[166],[59,1278,137],{"className":1279},[171],". A previsão do exemplo ",[59,1282,1284,1297],{"className":1283},[62],[59,1285,1287],{"className":1286},[66],[68,1288,1289],{"xmlns":70},[72,1290,1291,1295],{},[75,1292,1293],{},[78,1294,566],{},[83,1296,566],{"encoding":85},[59,1298,1300],{"className":1299,"ariaHidden":91},[90],[59,1301,1303,1307],{"className":1302},[95],[59,1304],{"className":1305,"style":1306},[99],"height:0.6595em;",[59,1308,566],{"className":1309},[104,158]," vira ",[22,1312,1313],{},"np.dot(w, X[i]) + b",", uma linha de código só, sem laço nenhum, não importa se ",[59,1316,1318,1331],{"className":1317},[62],[59,1319,1321],{"className":1320},[66],[68,1322,1323],{"xmlns":70},[72,1324,1325,1329],{},[75,1326,1327],{},[78,1328,131],{},[83,1330,131],{"encoding":85},[59,1332,1334],{"className":1333,"ariaHidden":91},[90],[59,1335,1337,1340],{"className":1336},[95],[59,1338],{"className":1339,"style":198},[99],[59,1341,131],{"className":1342},[104,158]," é 1 ou 100.",[27,1345,1347],{"id":1346},"fechando","Fechando",[1349,1350,1351,1365],"table",{},[1352,1353,1354],"thead",{},[1355,1356,1357,1362],"tr",{},[1358,1359,1361],"th",{"align":1360},"left","Tópico",[1358,1363,1364],{"align":1360},"O que ficou estabelecido",[1366,1367,1368,1377,1531,1539,1551,1562],"tbody",{},[1355,1369,1370,1374],{},[1371,1372,1373],"td",{"align":1360},"Por que NumPy",[1371,1375,1376],{"align":1360},"memória contígua e tipada, sem embrulho por elemento, é isso que dá velocidade",[1355,1378,1379,1382],{},[1371,1380,1381],{"align":1360},"Shape",[1371,1383,1384,1430,1431,1483,1484,1530],{"align":1360},[59,1385,1387,1406],{"className":1386},[62],[59,1388,1390],{"className":1389},[66],[68,1391,1392],{"xmlns":70},[72,1393,1394,1404],{},[75,1395,1396,1398,1400,1402],{},[125,1397,128],{"stretchy":127},[78,1399,131],{},[125,1401,134],{"separator":91},[125,1403,137],{"stretchy":127},[83,1405,140],{"encoding":85},[59,1407,1409],{"className":1408,"ariaHidden":91},[90],[59,1410,1412,1415,1418,1421,1424,1427],{"className":1411},[95],[59,1413],{"className":1414,"style":150},[99],[59,1416,128],{"className":1417},[154],[59,1419,131],{"className":1420},[104,158],[59,1422,134],{"className":1423},[162],[59,1425],{"className":1426,"style":167},[166],[59,1428,137],{"className":1429},[171]," é vetor, ",[59,1432,1434,1456],{"className":1433},[62],[59,1435,1437],{"className":1436},[66],[68,1438,1439],{"xmlns":70},[72,1440,1441,1453],{},[75,1442,1443,1445,1447,1449,1451],{},[125,1444,128],{"stretchy":127},[78,1446,992],{},[125,1448,134],{"separator":91},[78,1450,131],{},[125,1452,137],{"stretchy":127},[83,1454,1455],{"encoding":85},"(m,n)",[59,1457,1459],{"className":1458,"ariaHidden":91},[90],[59,1460,1462,1465,1468,1471,1474,1477,1480],{"className":1461},[95],[59,1463],{"className":1464,"style":150},[99],[59,1466,128],{"className":1467},[154],[59,1469,992],{"className":1470},[104,158],[59,1472,134],{"className":1473},[162],[59,1475],{"className":1476,"style":167},[166],[59,1478,131],{"className":1479},[104,158],[59,1481,137],{"className":1482},[171]," é matriz, e a vírgula solta em ",[59,1485,1487,1506],{"className":1486},[62],[59,1488,1490],{"className":1489},[66],[68,1491,1492],{"xmlns":70},[72,1493,1494,1504],{},[75,1495,1496,1498,1500,1502],{},[125,1497,128],{"stretchy":127},[78,1499,131],{},[125,1501,134],{"separator":91},[125,1503,137],{"stretchy":127},[83,1505,140],{"encoding":85},[59,1507,1509],{"className":1508,"ariaHidden":91},[90],[59,1510,1512,1515,1518,1521,1524,1527],{"className":1511},[95],[59,1513],{"className":1514,"style":150},[99],[59,1516,128],{"className":1517},[154],[59,1519,131],{"className":1520},[104,158],[59,1522,134],{"className":1523},[162],[59,1525],{"className":1526,"style":167},[166],[59,1528,137],{"className":1529},[171]," importa",[1355,1532,1533,1536],{},[1371,1534,1535],{"align":1360},"Indexação",[1371,1537,1538],{"align":1360},"começa em zero, e um índice numa matriz devolve uma dimensão a menos",[1355,1540,1541,1544],{},[1371,1542,1543],{"align":1360},"Fatiamento",[1371,1545,1546,1547,1550],{"align":1360},"fim é sempre exclusivo, igual ",[22,1548,1549],{},"range()"," do Python",[1355,1552,1553,1556],{},[1371,1554,1555],{"align":1360},"Produto escalar",[1371,1557,1558,1561],{"align":1360},[22,1559,1560],{},"np.dot(a, b)",", multiplica par a par e soma, devolve um escalar",[1355,1563,1564,1567],{},[1371,1565,1566],{"align":1360},"Vetorização",[1371,1568,1569],{"align":1360},"ganho real vem de memória contígua e tipo único, não de \"mágica de biblioteca\"",[11,1571,1572,1575,1576,1579,1580,1583,1584,1587],{},[35,1573,1574],{},"Como isso conecta com o resto da playlist:"," com essas ferramentas na mão, o modelo que você construiu no ",[526,1577,1578],{"href":528},"Lab 02"," com um ",[22,1581,1582],{},"w * x + b"," escrito à mão vira ",[22,1585,1586],{},"np.dot(w, x) + b",", funcionando pra qualquer número de features sem reescrever nada. É exatamente essa base que o curso usa pra estender tudo que você já viu (modelo, custo, gradiente descendente) pra regressão linear com várias variáveis.",[27,1589,1591],{"id":1590},"aplicação-prática","Aplicação prática",[11,1593,1594,1595,1601,1602,1604,1605,38],{},"Mesmo dataset real de imóveis dos posts anteriores (",[526,1596,1600],{"href":1597,"rel":1598},"https:\u002F\u002Fwww.kaggle.com\u002Fdatasets\u002Fdenkuznetz\u002Fhousing-prices-regression",[1599],"nofollow","Housing Prices Regression, Kaggle","). Esse post não treina nada, então aqui a ideia é só aplicar a mecânica de matriz\u002Fvetor em cima de nomes de coluna reais, em vez dos exemplos de brinquedo ",[22,1603,526],{}," e ",[22,1606,552],{},[306,1608,1610],{"className":308,"code":1609,"language":310,"meta":311,"style":311},"import pandas as pd\nimport numpy as np\n\ndf = pd.read_csv(\"real_estate_dataset.csv\")\n\nX = df[[\"Square_Feet\", \"Num_Bedrooms\"]].to_numpy()[:3]   # 3 primeiras casas, 2 features\n\nprint(\"X.shape:\", X.shape)        # (3, 2): 3 exemplos, 2 features\nprint(\"X[1]:\", X[1])              # a segunda casa inteira, vira vetor 1-D\nprint(\"X[:, 0]:\", X[:, 0])        # a coluna Square_Feet inteira, todas as casas\n",[22,1611,1612,1617,1621,1625,1630,1634,1639,1643,1648,1653],{"__ignoreMap":311},[59,1613,1614],{"class":316,"line":317},[59,1615,1616],{},"import pandas as pd\n",[59,1618,1619],{"class":316,"line":323},[59,1620,320],{},[59,1622,1623],{"class":316,"line":330},[59,1624,327],{"emptyLinePlaceholder":326},[59,1626,1627],{"class":316,"line":336},[59,1628,1629],{},"df = pd.read_csv(\"real_estate_dataset.csv\")\n",[59,1631,1632],{"class":316,"line":342},[59,1633,327],{"emptyLinePlaceholder":326},[59,1635,1636],{"class":316,"line":348},[59,1637,1638],{},"X = df[[\"Square_Feet\", \"Num_Bedrooms\"]].to_numpy()[:3]   # 3 primeiras casas, 2 features\n",[59,1640,1641],{"class":316,"line":353},[59,1642,327],{"emptyLinePlaceholder":326},[59,1644,1645],{"class":316,"line":359},[59,1646,1647],{},"print(\"X.shape:\", X.shape)        # (3, 2): 3 exemplos, 2 features\n",[59,1649,1650],{"class":316,"line":365},[59,1651,1652],{},"print(\"X[1]:\", X[1])              # a segunda casa inteira, vira vetor 1-D\n",[59,1654,1655],{"class":316,"line":877},[59,1656,1657],{},"print(\"X[:, 0]:\", X[:, 0])        # a coluna Square_Feet inteira, todas as casas\n",[1659,1660,1661],"blockquote",{},[11,1662,1663,1666,1667,1670,1671,1670,1674],{},[35,1664,1665],{},"Saída:"," ",[22,1668,1669],{},"X.shape: (3, 2)"," \u002F ",[22,1672,1673],{},"X[1]: [55.15  5.]",[22,1675,1676],{},"X[:, 0]: [143.64  55.15 202.96]",[306,1678,1680],{"className":308,"code":1679,"language":310,"meta":311,"style":311},"# Produto escalar de verdade, com pesos arbitrários só pra ilustrar a mecânica\n# (não treinamos nada nesse post, isso não é o ajuste \"certo\"):\nw = np.array([2000, 10000])\n\nfor i in range(X.shape[0]):\n    print(f\"np.dot(w, X[{i}]) = {np.dot(w, X[i]):,.0f}\")\n",[22,1681,1682,1687,1692,1697,1701,1706],{"__ignoreMap":311},[59,1683,1684],{"class":316,"line":317},[59,1685,1686],{},"# Produto escalar de verdade, com pesos arbitrários só pra ilustrar a mecânica\n",[59,1688,1689],{"class":316,"line":323},[59,1690,1691],{},"# (não treinamos nada nesse post, isso não é o ajuste \"certo\"):\n",[59,1693,1694],{"class":316,"line":330},[59,1695,1696],{},"w = np.array([2000, 10000])\n",[59,1698,1699],{"class":316,"line":336},[59,1700,327],{"emptyLinePlaceholder":326},[59,1702,1703],{"class":316,"line":342},[59,1704,1705],{},"for i in range(X.shape[0]):\n",[59,1707,1708],{"class":316,"line":348},[59,1709,1710],{},"    print(f\"np.dot(w, X[{i}]) = {np.dot(w, X[i]):,.0f}\")\n",[1659,1712,1713],{},[11,1714,1715,1666,1717,1670,1720,1670,1723],{},[35,1716,1665],{},[22,1718,1719],{},"np.dot(w, X[0]) = 297,280",[22,1721,1722],{},"np.dot(w, X[1]) = 160,300",[22,1724,1725],{},"np.dot(w, X[2]) = 455,920",[11,1727,1728,1729,1604,1732,1735,1736,1739,1740,1768],{},"Mesma conta, mesma mecânica do resto do post, só que rodando em cima de ",[22,1730,1731],{},"Square_Feet",[22,1733,1734],{},"Num_Bedrooms"," de verdade em vez de ",[22,1737,1738],{},"[1, 2, 3, 4]",". Treinar esses pesos de verdade (achar o ",[59,1741,1743,1756],{"className":1742},[62],[59,1744,1746],{"className":1745},[66],[68,1747,1748],{"xmlns":70},[72,1749,1750,1754],{},[75,1751,1752],{},[78,1753,1216],{"mathvariant":80},[83,1755,1219],{"encoding":85},[59,1757,1759],{"className":1758,"ariaHidden":91},[90],[59,1760,1762,1765],{"className":1761},[95],[59,1763],{"className":1764,"style":100},[99],[59,1766,1216],{"className":1767,"style":1232},[104,105]," que faz sentido pros dados) é conteúdo de mais pra frente no curso, com múltiplas features de uma vez.",[377,1770,1772],{"id":1771},"escolhendo-as-colunas-da-matriz-ao-vivo","Escolhendo as colunas da matriz, ao vivo",[11,1774,1775,1776,1804,1805,1604,1833,1863],{},"Lembra que ",[59,1777,1779,1792],{"className":1778},[62],[59,1780,1782],{"className":1781},[66],[68,1783,1784],{"xmlns":70},[72,1785,1786,1790],{},[75,1787,1788],{},[78,1789,958],{"mathvariant":80},[83,1791,961],{"encoding":85},[59,1793,1795],{"className":1794,"ariaHidden":91},[90],[59,1796,1798,1801],{"className":1797},[95],[59,1799],{"className":1800,"style":971},[99],[59,1802,958],{"className":1803},[104,105]," é só uma matriz, linha por exemplo, coluna por feature? Escolhe você mesmo quais duas colunas viram os eixos ",[59,1806,1808,1821],{"className":1807},[62],[59,1809,1811],{"className":1810},[66],[68,1812,1813],{"xmlns":70},[72,1814,1815,1819],{},[75,1816,1817],{},[78,1818,81],{},[83,1820,81],{"encoding":85},[59,1822,1824],{"className":1823,"ariaHidden":91},[90],[59,1825,1827,1830],{"className":1826},[95],[59,1828],{"className":1829,"style":198},[99],[59,1831,81],{"className":1832},[104,158],[59,1834,1836,1850],{"className":1835},[62],[59,1837,1839],{"className":1838},[66],[68,1840,1841],{"xmlns":70},[72,1842,1843,1848],{},[75,1844,1845],{},[78,1846,1847],{},"z",[83,1849,1847],{"encoding":85},[59,1851,1853],{"className":1852,"ariaHidden":91},[90],[59,1854,1856,1859],{"className":1855},[95],[59,1857],{"className":1858,"style":198},[99],[59,1860,1847],{"className":1861,"style":1862},[104,158],"margin-right:0.044em;"," do gráfico abaixo (a altura fica sempre com o preço) e gira pra sentir como cada combinação de colunas se relaciona com o preço das 50 casas:",[1865,1866],"housing-feature-explorer3d",{},[1868,1869,1870],"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":311,"searchDepth":323,"depth":323,"links":1872},[1873,1874,1878,1879,1880,1881,1882],{"id":29,"depth":323,"text":30},{"id":53,"depth":323,"text":54,"children":1875},[1876,1877],{"id":379,"depth":330,"text":380},{"id":444,"depth":330,"text":445},{"id":506,"depth":323,"text":507},{"id":889,"depth":323,"text":890},{"id":939,"depth":323,"text":940},{"id":1346,"depth":323,"text":1347},{"id":1590,"depth":323,"text":1591,"children":1883},[1884],{"id":1771,"depth":330,"text":1772},null,"2026-08-18","Por que todo código sério de ML usa NumPy em vez de lista Python: vetores, matrizes, produto escalar, e a diferença real (não a lenda) entre laço e conta vetorizada.","md",{},"\u002Fpt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization","machine-learning-specialization",{"title":6,"description":1887},"published","pt\u002Fplaylists\u002Fmachine-learning-specialization\u002Fw2-lab01-numpy-vectorization",[1896,1897,1898],"numpy","vetorizacao","ferramentas","0awsiRJzZCdtP1PsGWrG5GOwbVQZBe60Esxs9O-4wLo",1787338983652]