manipulation.py 251 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931
  1. # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # TODO: define functions to manipulate a tensor
  15. import numpy as np
  16. import paddle
  17. from paddle import _C_ops
  18. from paddle.tensor import fill_constant
  19. from paddle.utils.inplace_utils import inplace_apis_in_dygraph_only
  20. from ..base.data_feeder import (
  21. check_dtype,
  22. check_type,
  23. check_variable_and_dtype,
  24. convert_dtype,
  25. )
  26. from ..base.framework import Variable, default_main_program
  27. from ..framework import (
  28. LayerHelper,
  29. convert_np_dtype_to_dtype_,
  30. core,
  31. dygraph_only,
  32. in_dynamic_mode,
  33. in_dynamic_or_pir_mode,
  34. in_pir_mode,
  35. )
  36. from .creation import _complex_to_real_dtype, _real_to_complex_dtype, zeros
  37. __all__ = []
  38. def tensor_array_to_tensor(input, axis=1, use_stack=False, name=None):
  39. r"""
  40. This function concatenates or stacks all tensors in the input LoDTensorArray
  41. along the axis mentioned and returns that as the output.
  42. For Example:
  43. .. code-block:: text
  44. Case 1:
  45. Given:
  46. input.data = {[[0.6, 0.1, 0.3],
  47. [0.5, 0.3, 0.2]],
  48. [[1.3],
  49. [1.8]],
  50. [[2.3, 2.1],
  51. [2.5, 2.4]]}
  52. axis = 1, use_stack = False
  53. Then:
  54. output.data = [[0.6, 0.1, 0.3, 1.3, 2.3, 2.1],
  55. [0.5, 0.3, 0.2, 1.8, 2.5, 2.4]]
  56. output_index.data = [3, 1, 2]
  57. Case 2:
  58. Given:
  59. input.data = {[[0.6, 0.1],
  60. [0.5, 0.3]],
  61. [[0.3, 1.3],
  62. [0.2, 1.8]],
  63. [[2.3, 2.1],
  64. [2.5, 2.4]]}
  65. axis = 1, use_stack = True
  66. Then:
  67. output.data = [[[0.6, 0.1]
  68. [0.3, 1.3]
  69. [2.3, 2.1],
  70. [[0.5, 0.3]
  71. [0.2, 1.8]
  72. [2.5, 2.4]]]
  73. output_index.data = [2, 2, 2]
  74. Args:
  75. input(TensorArray): A TensorArray variable.
  76. axis(int): The axis along which the tensors in attr::`input` will be
  77. concatenated or stacked.
  78. use_stack(bool): Act as concat_op or stack_op. For stack mode, all
  79. tensors in the tensor array must have the same shape.
  80. name(str|None): A name for this layer(optional). If set None, the layer
  81. will be named automatically.
  82. Returns:
  83. Tensor: The concatenated or stacked tensor variable.
  84. Tensor: A 1-D tensor variable with int32 data type. The data in this \
  85. tensor contains all input including tensors' sizes along the axis.
  86. Examples:
  87. .. code-block:: python
  88. >>> import numpy
  89. >>> import paddle
  90. >>> x0 = paddle.assign(numpy.random.rand(2, 2).astype("float32"))
  91. >>> x1 = paddle.assign(numpy.random.rand(2, 2).astype("float32"))
  92. >>> i = paddle.full(shape=[1], dtype="int64", fill_value=0)
  93. >>> array = paddle.tensor.array.create_array(dtype='float32')
  94. >>> paddle.tensor.array.array_write(x0, i, array)
  95. >>> paddle.tensor.array.array_write(x1, i + 1, array)
  96. >>> output, output_index = paddle.tensor.manipulation.tensor_array_to_tensor(input=array)
  97. """
  98. if in_dynamic_mode():
  99. assert isinstance(
  100. input, list
  101. ), "The 'input' in tensor_array_to_tensor must be list"
  102. from paddle import concat, stack
  103. op = stack if use_stack else concat
  104. res = op(input, axis=axis)
  105. sizes = paddle.to_tensor(np.array([int(x.shape[axis]) for x in input]))
  106. return res, sizes
  107. elif in_pir_mode():
  108. check_type(
  109. input,
  110. 'input',
  111. (list, paddle.pir.Value),
  112. 'tensor_array_to_tensor',
  113. )
  114. if isinstance(input, list):
  115. for i, input_x in enumerate(input):
  116. check_type(
  117. input_x,
  118. 'input[' + str(i) + ']',
  119. paddle.pir.Value,
  120. 'tensor_array_to_tensor',
  121. )
  122. if not input_x.is_dense_tensor_array_type():
  123. raise TypeError("input should be tensor array variable")
  124. else:
  125. if not input.is_dense_tensor_array_type():
  126. raise TypeError("input should be tensor array variable")
  127. return paddle._pir_ops.array_to_tensor(input, axis, use_stack)
  128. else:
  129. check_type(input, 'input', (list, Variable), 'tensor_array_to_tensor')
  130. if isinstance(input, list):
  131. for i, input_x in enumerate(input):
  132. check_type(
  133. input_x,
  134. 'input[' + str(i) + ']',
  135. Variable,
  136. 'tensor_array_to_tensor',
  137. )
  138. helper = LayerHelper('tensor_array_to_tensor', **locals())
  139. out = helper.create_variable_for_type_inference(
  140. dtype=helper.input_dtype()
  141. )
  142. out_index = helper.create_variable_for_type_inference(dtype="int32")
  143. helper.append_op(
  144. type='tensor_array_to_tensor',
  145. inputs={'X': input},
  146. outputs={'Out': [out], 'OutIndex': [out_index]},
  147. attrs={'axis': axis, 'use_stack': use_stack},
  148. )
  149. return out, out_index
  150. def cast(x, dtype):
  151. """
  152. Take in the Tensor :attr:`x` with :attr:`x.dtype` and cast it
  153. to the output with :attr:`dtype`. It's meaningless if the output dtype
  154. equals the input dtype, but it's fine if you do so.
  155. Args:
  156. x (Tensor): An input N-D Tensor with data type bool, float16,
  157. float32, float64, int32, int64, uint8.
  158. dtype (np.dtype|str): Data type of the output:
  159. bool, float16, float32, float64, int8, int32, int64, uint8.
  160. Returns:
  161. Tensor, A Tensor with the same shape as input's.
  162. Examples:
  163. .. code-block:: python
  164. >>> import paddle
  165. >>> x = paddle.to_tensor([2, 3, 4], 'float64')
  166. >>> y = paddle.cast(x, 'uint8')
  167. """
  168. if not isinstance(dtype, (core.VarDesc.VarType, core.DataType)):
  169. dtype = convert_np_dtype_to_dtype_(dtype)
  170. if in_dynamic_or_pir_mode():
  171. return _C_ops.cast(x, dtype)
  172. else:
  173. check_variable_and_dtype(
  174. x,
  175. 'x',
  176. [
  177. 'bool',
  178. 'float16',
  179. 'float32',
  180. 'float64',
  181. 'int16',
  182. 'int32',
  183. 'int64',
  184. 'uint8',
  185. 'uint16',
  186. ],
  187. 'cast',
  188. )
  189. check_dtype(
  190. dtype,
  191. 'dtype',
  192. [
  193. 'bool',
  194. 'float16',
  195. 'float32',
  196. 'float64',
  197. 'int8',
  198. 'int16',
  199. 'int32',
  200. 'int64',
  201. 'uint8',
  202. 'uint16',
  203. ],
  204. 'cast',
  205. )
  206. helper = LayerHelper('cast', **locals())
  207. out = helper.create_variable_for_type_inference(
  208. dtype=dtype, stop_gradient=x.stop_gradient
  209. )
  210. helper.append_op(
  211. type='cast',
  212. inputs={'X': [x]},
  213. outputs={'Out': [out]},
  214. attrs={'in_dtype': x.dtype, 'out_dtype': out.dtype},
  215. )
  216. return out
  217. @inplace_apis_in_dygraph_only
  218. def cast_(x, dtype):
  219. """
  220. Inplace version of ``cast`` API, the output Tensor will be inplaced with input ``x``.
  221. Please refer to :ref:`api_paddle_cast`.
  222. """
  223. if in_dynamic_mode():
  224. if not isinstance(dtype, core.VarDesc.VarType):
  225. dtype = convert_np_dtype_to_dtype_(dtype)
  226. return _C_ops.cast_(x, dtype)
  227. def slice(input, axes, starts, ends):
  228. """
  229. This operator produces a slice of ``input`` along multiple axes. Similar to numpy:
  230. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
  231. Slice uses ``axes``, ``starts`` and ``ends`` attributes to specify the start and
  232. end dimension for each axis in the list of axes and Slice uses this information
  233. to slice the input data tensor. If a negative value is passed to
  234. ``starts`` or ``ends`` such as :math:`-i`, it represents the reverse position of the
  235. axis :math:`i-1` (here 0 is the initial position).
  236. If the value passed to ``starts`` or ``ends`` is greater than n
  237. (the number of elements in this dimension), it represents n.
  238. For slicing to the end of a dimension with unknown size, it is recommended
  239. to pass in INT_MAX. The size of ``axes`` must be equal to ``starts`` and ``ends``.
  240. Following examples will explain how slice works:
  241. .. code-block:: text
  242. Case1:
  243. Given:
  244. data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
  245. axes = [0, 1]
  246. starts = [1, 0]
  247. ends = [2, 3]
  248. Then:
  249. result = [ [5, 6, 7], ]
  250. Case2:
  251. Given:
  252. data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
  253. axes = [0, 1]
  254. starts = [0, 1]
  255. ends = [-1, 1000] # -1 denotes the reverse 0th position of dimension 0.
  256. Then:
  257. result = [ [2, 3, 4], ] # result = data[0:1, 1:4]
  258. Args:
  259. input (Tensor): A ``Tensor`` . The data type is ``float16``, ``float32``, ``float64``, ``int32`` or ``int64``.
  260. axes (list|tuple): The data type is ``int32`` . Axes that `starts` and `ends` apply to .
  261. starts (list|tuple|Tensor): The data type is ``int32`` . If ``starts`` is a list or tuple, each element of
  262. it should be integer or 0-D int Tensor with shape []. If ``starts`` is an Tensor, it should be an 1-D Tensor.
  263. It represents starting indices of corresponding axis in ``axes``.
  264. ends (list|tuple|Tensor): The data type is ``int32`` . If ``ends`` is a list or tuple, each element of
  265. it should be integer or 0-D int Tensor with shape []. If ``ends`` is an Tensor, it should be an 1-D Tensor .
  266. It represents ending indices of corresponding axis in ``axes``.
  267. Returns:
  268. Tensor, A ``Tensor``. The data type is same as ``input``.
  269. Examples:
  270. .. code-block:: python
  271. >>> import paddle
  272. >>> input = paddle.rand(shape=[4, 5, 6], dtype='float32')
  273. >>> # example 1:
  274. >>> # attr starts is a list which doesn't contain tensor.
  275. >>> axes = [0, 1, 2]
  276. >>> starts = [-3, 0, 2]
  277. >>> ends = [3, 2, 4]
  278. >>> sliced_1 = paddle.slice(input, axes=axes, starts=starts, ends=ends)
  279. >>> # sliced_1 is input[1:3, 0:2, 2:4].
  280. >>> # example 2:
  281. >>> # attr starts is a list which contain tensor.
  282. >>> minus_3 = paddle.full([1], -3, "int32")
  283. >>> sliced_2 = paddle.slice(input, axes=axes, starts=[minus_3, 0, 2], ends=ends)
  284. >>> # sliced_2 is input[1:3, 0:2, 2:4].
  285. """
  286. if isinstance(axes, (list, tuple)):
  287. axes = list(axes)
  288. if len(axes) == 0:
  289. raise ValueError("Input axes should not be an empty list/tuple.")
  290. for i in range(len(axes)):
  291. if axes[i] < 0:
  292. axes[i] = max(0, axes[i] + len(input.shape))
  293. else:
  294. axes[i] = min(len(input.shape) - 1, axes[i])
  295. else:
  296. raise ValueError(
  297. f"Input axes must be a python list or tuple, but received {type(axes)}"
  298. )
  299. if in_dynamic_mode():
  300. attrs = ()
  301. starts_tensor = None
  302. ends_tensor = None
  303. infer_flags = [1 for i in range(len(axes))]
  304. if isinstance(starts, (list, tuple)):
  305. starts = [
  306. item.item(0) if isinstance(item, core.eager.Tensor) else item
  307. for item in starts
  308. ]
  309. elif isinstance(starts, core.eager.Tensor):
  310. tensor_t = starts.numpy(False)
  311. starts = list(tensor_t)
  312. infer_flags = [-1 for i in range(len(axes))]
  313. if isinstance(ends, (list, tuple)):
  314. ends = [
  315. item.item(0) if isinstance(item, core.eager.Tensor) else item
  316. for item in ends
  317. ]
  318. elif isinstance(ends, core.eager.Tensor):
  319. tensor_t = ends.numpy(False)
  320. ends = list(tensor_t)
  321. infer_flags = [-1 for i in range(len(axes))]
  322. return _C_ops.slice(input, axes, starts, ends, infer_flags, [])
  323. elif in_pir_mode():
  324. if not isinstance(starts, (list, tuple, paddle.pir.Value)):
  325. raise ValueError(
  326. "Input starts must be an Value, python list or tuple."
  327. )
  328. if not isinstance(ends, (list, tuple, paddle.pir.Value)):
  329. raise ValueError(
  330. "Input ends must be an Value, python list or tuple."
  331. )
  332. infer_flags = [1 for i in range(len(axes))]
  333. # starts
  334. if isinstance(starts, paddle.pir.Value):
  335. starts.stop_gradient = True
  336. infer_flags = [-1 for i in range(len(axes))]
  337. elif isinstance(starts, (list, tuple)):
  338. if paddle.utils._contain_var(starts):
  339. for i, dim in enumerate(starts):
  340. if isinstance(dim, paddle.pir.Value):
  341. infer_flags[i] = -1
  342. starts = paddle.utils.get_int_tensor_list(starts)
  343. # ends
  344. if isinstance(ends, paddle.pir.Value):
  345. ends.stop_gradient = True
  346. infer_flags = [-1 for i in range(len(axes))]
  347. elif isinstance(ends, (list, tuple)):
  348. if paddle.utils._contain_var(ends):
  349. for i, dim in enumerate(ends):
  350. if isinstance(dim, paddle.pir.Value):
  351. infer_flags[i] = -1
  352. ends = paddle.utils.get_int_tensor_list(ends)
  353. return _C_ops.slice(input, axes, starts, ends, infer_flags, [])
  354. else:
  355. if not isinstance(starts, (list, tuple, Variable)):
  356. raise ValueError(
  357. "Input starts must be an Variable, python list or tuple."
  358. )
  359. if not isinstance(ends, (list, tuple, Variable)):
  360. raise ValueError(
  361. "Input ends must be an Variable, python list or tuple."
  362. )
  363. helper = LayerHelper('slice', **locals())
  364. inputs = {'Input': input}
  365. attrs = {'axes': axes}
  366. infer_flags = [1 for i in range(len(axes))]
  367. # starts
  368. if isinstance(starts, Variable):
  369. starts.stop_gradient = True
  370. inputs['StartsTensor'] = starts
  371. infer_flags = [-1 for i in range(len(axes))]
  372. elif isinstance(starts, (list, tuple)):
  373. attrs['starts'] = []
  374. if paddle.utils._contain_var(starts):
  375. inputs[
  376. 'StartsTensorList'
  377. ] = paddle.utils._convert_to_tensor_list(starts)
  378. for i, dim in enumerate(starts):
  379. if isinstance(dim, Variable):
  380. attrs['starts'].append(-1)
  381. infer_flags[i] = -1
  382. else:
  383. attrs['starts'].append(dim)
  384. else:
  385. attrs['starts'] = starts
  386. # ends
  387. if isinstance(ends, Variable):
  388. ends.stop_gradient = True
  389. inputs['EndsTensor'] = ends
  390. infer_flags = [-1 for i in range(len(axes))]
  391. elif isinstance(ends, (list, tuple)):
  392. attrs['ends'] = []
  393. if paddle.utils._contain_var(ends):
  394. inputs['EndsTensorList'] = paddle.utils._convert_to_tensor_list(
  395. ends
  396. )
  397. for i, dim in enumerate(ends):
  398. if isinstance(dim, Variable):
  399. attrs['ends'].append(-1)
  400. infer_flags[i] = -1
  401. else:
  402. attrs['ends'].append(dim)
  403. else:
  404. attrs['ends'] = ends
  405. # infer_flags
  406. attrs['infer_flags'] = infer_flags
  407. out = helper.create_variable_for_type_inference(
  408. dtype=helper.input_dtype('input')
  409. )
  410. helper.append_op(
  411. type='slice', inputs=inputs, attrs=attrs, outputs={'Out': out}
  412. )
  413. return out
  414. def transpose(x, perm, name=None):
  415. """
  416. Permute the data dimensions of `input` according to `perm`.
  417. The `i`-th dimension of the returned tensor will correspond to the
  418. perm[i]-th dimension of `input`.
  419. Args:
  420. x (Tensor): The input Tensor. It is a N-D Tensor of data types bool, float32, float64, int32.
  421. perm (list|tuple): Permute the input according to the data of perm.
  422. name (str): The name of this layer. It is optional.
  423. Returns:
  424. Tensor, A transposed n-D Tensor, with data type being bool, float32, float64, int32, int64.
  425. For Example:
  426. .. code-block:: text
  427. x = [[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]
  428. [[13 14 15 16] [17 18 19 20] [21 22 23 24]]]
  429. shape(x) = [2,3,4]
  430. # Example 1
  431. perm0 = [1,0,2]
  432. y_perm0 = [[[ 1 2 3 4] [13 14 15 16]]
  433. [[ 5 6 7 8] [17 18 19 20]]
  434. [[ 9 10 11 12] [21 22 23 24]]]
  435. shape(y_perm0) = [3,2,4]
  436. # Example 2
  437. perm1 = [2,1,0]
  438. y_perm1 = [[[ 1 13] [ 5 17] [ 9 21]]
  439. [[ 2 14] [ 6 18] [10 22]]
  440. [[ 3 15] [ 7 19] [11 23]]
  441. [[ 4 16] [ 8 20] [12 24]]]
  442. shape(y_perm1) = [4,3,2]
  443. Examples:
  444. .. code-block:: python
  445. >>> import paddle
  446. >>> x = paddle.randn([2, 3, 4])
  447. >>> x_transposed = paddle.transpose(x, perm=[1, 0, 2])
  448. >>> print(x_transposed.shape)
  449. [3, 2, 4]
  450. """
  451. if in_dynamic_or_pir_mode():
  452. return _C_ops.transpose(x, perm)
  453. else:
  454. check_variable_and_dtype(
  455. x,
  456. 'x',
  457. [
  458. 'bool',
  459. 'float16',
  460. 'float32',
  461. 'float64',
  462. 'int32',
  463. 'int64',
  464. 'uint16',
  465. 'complex64',
  466. 'complex128',
  467. ],
  468. 'transpose',
  469. )
  470. check_type(perm, 'perm', (list, tuple), 'transpose')
  471. if isinstance(perm, tuple):
  472. perm = list(perm)
  473. if len(perm) != len(x.shape):
  474. raise ValueError(
  475. "Input(perm) is the permutation of dimensions of Input(x), "
  476. "its length should be equal to dimensions of Input(x), "
  477. f"but received dimension of Input(x) is {len(x.shape)}, "
  478. f"the length of Input(perm) is {len(perm)}."
  479. )
  480. for idx, dim in enumerate(perm):
  481. if dim >= len(x.shape):
  482. raise ValueError(
  483. "Each element in Input(perm) should be less than Input(x)'s dimension, "
  484. "but %d-th element in Input(perm) is %d which exceeds Input(x)'s "
  485. "dimension %d." % (idx, perm[idx], len(x.shape))
  486. )
  487. helper = LayerHelper('transpose', **locals())
  488. out = helper.create_variable_for_type_inference(x.dtype)
  489. x_shape = helper.create_variable_for_type_inference(x.dtype)
  490. helper.append_op(
  491. type='transpose2',
  492. inputs={'X': [x]},
  493. outputs={'Out': [out], 'XShape': [x_shape]},
  494. attrs={'axis': perm},
  495. )
  496. return out
  497. def unstack(x, axis=0, num=None):
  498. """
  499. This layer unstacks input Tensor :code:`x` into several Tensors along :code:`axis`.
  500. If :code:`axis` < 0, it would be replaced with :code:`axis+rank(x)`.
  501. If :code:`num` is None, it would be inferred from :code:`x.shape[axis]`,
  502. and if :code:`x.shape[axis]` <= 0 or is unknown, :code:`ValueError` is
  503. raised.
  504. Args:
  505. x (Tensor): Input Tensor. It is a N-D Tensors of data types float32, float64, int32, int64, complex64, complex128.
  506. axis (int): The axis along which the input is unstacked.
  507. num (int|None): The number of output variables.
  508. Returns:
  509. list(Tensor), The unstacked Tensors list. The list elements are N-D Tensors of data types float32, float64, int32, int64, complex64, complex128.
  510. Examples:
  511. .. code-block:: python
  512. >>> import paddle
  513. >>> x = paddle.ones(name='x', shape=[2, 3, 5], dtype='float32') # create a tensor with shape=[2, 3, 5]
  514. >>> y = paddle.unstack(x, axis=1) # unstack with second axis, which results 3 tensors with shape=[2, 5]
  515. """
  516. if not (-x.ndim <= axis < x.ndim):
  517. raise ValueError(f'`axis` must be in the range [-{x.ndim}, {x.ndim})')
  518. if num is not None and (num < 0 or num > x.shape[axis]):
  519. raise ValueError(f'`num` must be in the range [0, {x.shape[axis]})')
  520. if in_dynamic_or_pir_mode():
  521. if num is None:
  522. num = x.shape[axis]
  523. if num == 0:
  524. return []
  525. return _C_ops.unstack(x, axis, num)
  526. else:
  527. helper = LayerHelper('unstack', **locals())
  528. if num is None:
  529. if axis is None or x.shape[axis] <= 0:
  530. raise ValueError('unknown unstack number')
  531. else:
  532. num = x.shape[axis]
  533. outs = []
  534. for _ in range(num):
  535. outs.append(helper.create_variable_for_type_inference(x.dtype))
  536. helper.append_op(
  537. type='unstack',
  538. inputs={'X': [x]},
  539. outputs={'Y': outs},
  540. attrs={'axis': axis, 'num': num},
  541. )
  542. return outs
  543. def shard_index(input, index_num, nshards, shard_id, ignore_value=-1):
  544. """
  545. Reset the values of `input` according to the shard it belongs to.
  546. Every value in `input` must be a non-negative integer, and
  547. the parameter `index_num` represents the integer above the maximum
  548. value of `input`. Thus, all values in `input` must be in the range
  549. [0, index_num) and each value can be regarded as the offset to the beginning
  550. of the range. The range is further split into multiple shards. Specifically,
  551. we first compute the `shard_size` according to the following formula,
  552. which represents the number of integers each shard can hold. So for the
  553. i'th shard, it can hold values in the range [i*shard_size, (i+1)*shard_size).
  554. ::
  555. shard_size = (index_num + nshards - 1) // nshards
  556. For each value `v` in `input`, we reset it to a new value according to the
  557. following formula:
  558. ::
  559. v = v - shard_id * shard_size if shard_id * shard_size <= v < (shard_id+1) * shard_size else ignore_value
  560. That is, the value `v` is set to the new offset within the range represented by the shard `shard_id`
  561. if it in the range. Otherwise, we reset it to be `ignore_value`.
  562. Args:
  563. input (Tensor): Input tensor with data type int64 or int32. It's last dimension must be 1.
  564. index_num (int): An integer represents the integer above the maximum value of `input`.
  565. nshards (int): The number of shards.
  566. shard_id (int): The index of the current shard.
  567. ignore_value (int, optional): An integer value out of sharded index range. The default value is -1.
  568. Returns:
  569. Tensor.
  570. Examples:
  571. .. code-block:: python
  572. >>> import paddle
  573. >>> label = paddle.to_tensor([[16], [1]], "int64")
  574. >>> shard_label = paddle.shard_index(input=label,
  575. ... index_num=20,
  576. ... nshards=2,
  577. ... shard_id=0)
  578. >>> print(shard_label.numpy())
  579. [[-1]
  580. [ 1]]
  581. """
  582. if in_dynamic_or_pir_mode():
  583. return _C_ops.shard_index(
  584. input, index_num, nshards, shard_id, ignore_value
  585. )
  586. check_variable_and_dtype(input, 'input', ['int64', 'int32'], 'shard_index')
  587. op_type = 'shard_index'
  588. helper = LayerHelper(op_type, **locals())
  589. if shard_id < 0 or shard_id >= nshards:
  590. raise ValueError(
  591. 'The shard_id(%d) should be in [0, %d)' % (shard_id, nshards)
  592. )
  593. out = helper.create_variable_for_type_inference(dtype=input.dtype)
  594. helper.append_op(
  595. type=op_type,
  596. inputs={'X': [input]},
  597. outputs={'Out': out},
  598. attrs={
  599. 'index_num': index_num,
  600. 'nshards': nshards,
  601. 'shard_id': shard_id,
  602. 'ignore_value': ignore_value,
  603. },
  604. stop_gradient=True,
  605. )
  606. return out
  607. def crop(x, shape=None, offsets=None, name=None):
  608. """
  609. Crop input into output, as specified by offsets and shape.
  610. .. code-block:: text
  611. * Case 1 (input is a 2-D Tensor):
  612. Input:
  613. X.shape = [3, 5]
  614. X.data = [[0, 1, 2, 0, 0],
  615. [0, 3, 4, 0, 0],
  616. [0, 0, 0, 0, 0]]
  617. Parameters:
  618. shape = [2, 2]
  619. offsets = [0, 1]
  620. Output:
  621. Out.shape = [2, 2]
  622. Out.data = [[1, 2],
  623. [3, 4]]
  624. * Case 2 (input is a 3-D Tensor):
  625. Input:
  626. X.shape = [2, 3, 4]
  627. X.data = [[[0, 1, 2, 3],
  628. [0, 5, 6, 7],
  629. [0, 0, 0, 0]],
  630. [[0, 3, 4, 5],
  631. [0, 6, 7, 8],
  632. [0, 0, 0, 0]]]
  633. Parameters:
  634. shape = [2, 2, -1]
  635. offsets = [0, 0, 1]
  636. Output:
  637. Out.shape = [2, 2, 3]
  638. Out.data = [[[1, 2, 3],
  639. [5, 6, 7]],
  640. [[3, 4, 5],
  641. [6, 7, 8]]]
  642. Parameters:
  643. x (Tensor): 1-D to 6-D Tensor, the data type is float32, float64, int32 or int64.
  644. shape (list|tuple|Tensor, optional): The output shape is specified
  645. by `shape`. Its data type is int32. If a list/tuple, it's length must be
  646. the same as the dimension size of `x`. If a Tensor, it should be a 1-D Tensor.
  647. When it is a list, each element can be an integer or a Tensor of shape: [1].
  648. If Variable contained, it is suitable for the case that the shape may
  649. be changed each iteration.
  650. offsets (list|tuple|Variable, optional): Specifies the cropping
  651. offsets at each dimension. Its data type is int32. If a list/tuple, it's length
  652. must be the same as the dimension size of `x`. If a Tensor, it should be a 1-D
  653. Tensor. When it is a list, each element can be an integer or a Tensor of shape: [1].
  654. If Variable contained, it is suitable for the case that the offsets may be changed
  655. each iteration. Default: None, the offsets are 0 at each dimension.
  656. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  657. Returns:
  658. Tensor, The cropped Tensor has same data type with `x`.
  659. Examples:
  660. .. code-block:: python
  661. >>> import paddle
  662. >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
  663. >>> # x.shape = [3, 3]
  664. >>> # x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
  665. >>> # shape can be a 1-D Tensor or list or tuple.
  666. >>> shape = paddle.to_tensor([2, 2], dtype='int32')
  667. >>> # shape = [2, 2]
  668. >>> # shape = (2, 2)
  669. >>> out = paddle.crop(x, shape)
  670. >>> # out.shape = [2, 2]
  671. >>> # out = [[1,2], [4,5]]
  672. >>> # offsets can be a 1-D Tensor or list or tuple.
  673. >>> offsets = paddle.to_tensor([0, 1], dtype='int32')
  674. >>> # offsets = [1, 0]
  675. >>> # offsets = (1, 1)
  676. >>> out = paddle.crop(x, shape, offsets)
  677. >>> # out.shape = [2, 2]
  678. >>> # if offsets = [0, 0], out = [[1,2], [4,5]]
  679. >>> # if offsets = [0, 1], out = [[2,3], [5,6]]
  680. >>> # if offsets = [1, 0], out = [[4,5], [7,8]]
  681. >>> # if offsets = [1, 1], out = [[5,6], [8,9]]
  682. """
  683. helper = LayerHelper('crop_tensor', **locals())
  684. check_variable_and_dtype(
  685. x, 'x', ['float32', 'float64', 'int32', 'int64'], 'crop_tensor'
  686. )
  687. check_type(
  688. shape,
  689. 'shape',
  690. (list, tuple, Variable, type(None), paddle.pir.Value),
  691. 'crop_tensor',
  692. )
  693. check_type(
  694. offsets,
  695. 'offsets',
  696. (list, tuple, Variable, type(None), paddle.pir.Value),
  697. 'crop_tensor',
  698. )
  699. if offsets is None:
  700. offsets = [0] * len(x.shape)
  701. if shape is None:
  702. shape = x.shape
  703. if in_dynamic_mode():
  704. return _C_ops.crop(x, shape, offsets)
  705. def _attr_shape_check(shape_val):
  706. if not isinstance(shape_val, int):
  707. raise TypeError(
  708. "Attr(shape)'s dtype of Op(crop_tensor) should be int32, but received: %s."
  709. % type(shape_val)
  710. )
  711. if shape_val == 0:
  712. raise ValueError(
  713. "Attr(shape) of Op(crop_tensor) should not be zero, but received: %s."
  714. % str(shape_val)
  715. )
  716. if shape_val < -1:
  717. raise ValueError(
  718. "When the element in Attr(shape) of Op(crop_tensor) is negative, only -1 is supported, but received: %s."
  719. % str(shape_val)
  720. )
  721. def _attr_offsets_check(offset_val):
  722. if not isinstance(offset_val, int):
  723. raise TypeError(
  724. "Attr(offsets)'s dtype of Op(crop_tensor) should be int32, but received: %s."
  725. % type(offset_val)
  726. )
  727. if offset_val < 0:
  728. raise ValueError(
  729. "Attr(offsets) of Op(crop_tensor) should be greater or equal to zero, but received: %s."
  730. % str(offset_val)
  731. )
  732. if in_pir_mode():
  733. if isinstance(offsets, paddle.pir.Value):
  734. offsets.stop_gradient = True
  735. elif paddle.utils._contain_var(offsets):
  736. new_offsets_tensor = []
  737. for dim in offsets:
  738. if isinstance(dim, paddle.pir.Value):
  739. dim.stop_gradient = True
  740. new_offsets_tensor.append(dim)
  741. else:
  742. _attr_offsets_check(dim)
  743. temp_out = fill_constant([1], 'int32', dim, force_cpu=True)
  744. new_offsets_tensor.append(temp_out)
  745. offsets = new_offsets_tensor
  746. else:
  747. for offset in offsets:
  748. _attr_offsets_check(offset)
  749. if isinstance(shape, paddle.pir.Value):
  750. shape.stop_gradient = True
  751. elif paddle.utils._contain_var(shape):
  752. new_shape_tensor = []
  753. for dim_size in shape:
  754. if isinstance(dim_size, paddle.pir.Value):
  755. dim_size.stop_gradient = True
  756. new_shape_tensor.append(dim_size)
  757. else:
  758. _attr_shape_check(dim_size)
  759. temp_out = fill_constant(
  760. [1], 'int32', dim_size, force_cpu=True
  761. )
  762. new_shape_tensor.append(temp_out)
  763. shape = new_shape_tensor
  764. else:
  765. for dim_size in shape:
  766. _attr_shape_check(dim_size)
  767. return _C_ops.crop(x, shape, offsets)
  768. out = helper.create_variable_for_type_inference(x.dtype)
  769. ipts = {'X': x}
  770. attrs = {}
  771. if isinstance(offsets, Variable):
  772. offsets.stop_gradient = True
  773. ipts['Offsets'] = offsets
  774. attrs['offsets'] = [-1] * len(x.shape)
  775. elif paddle.utils._contain_var(offsets):
  776. new_offsets_tensor = []
  777. offsets_attr = []
  778. for dim in offsets:
  779. if isinstance(dim, Variable):
  780. dim.stop_gradient = True
  781. new_offsets_tensor.append(dim)
  782. offsets_attr.append(-1)
  783. else:
  784. _attr_offsets_check(dim)
  785. temp_out = helper.create_variable_for_type_inference('int32')
  786. fill_constant([1], 'int32', dim, force_cpu=True, out=temp_out)
  787. new_offsets_tensor.append(temp_out)
  788. offsets_attr.append(dim)
  789. ipts['OffsetsTensor'] = new_offsets_tensor
  790. attrs['offsets'] = offsets_attr
  791. else:
  792. for offset in offsets:
  793. _attr_offsets_check(offset)
  794. attrs['offsets'] = offsets
  795. if isinstance(shape, Variable):
  796. shape.stop_gradient = True
  797. ipts['Shape'] = shape
  798. elif paddle.utils._contain_var(shape):
  799. new_shape_tensor = []
  800. shape_attr = []
  801. for dim_size in shape:
  802. if isinstance(dim_size, Variable):
  803. dim_size.stop_gradient = True
  804. new_shape_tensor.append(dim_size)
  805. shape_attr.append(0)
  806. else:
  807. _attr_shape_check(dim_size)
  808. temp_out = helper.create_variable_for_type_inference('int32')
  809. fill_constant(
  810. [1], 'int32', dim_size, force_cpu=True, out=temp_out
  811. )
  812. new_shape_tensor.append(temp_out)
  813. shape_attr.append(dim_size)
  814. ipts['ShapeTensor'] = new_shape_tensor
  815. attrs['shape'] = shape_attr
  816. else:
  817. for dim_size in shape:
  818. _attr_shape_check(dim_size)
  819. attrs['shape'] = shape
  820. helper.append_op(
  821. type='crop_tensor',
  822. inputs=ipts,
  823. outputs={'Out': out},
  824. attrs=None if len(attrs) == 0 else attrs,
  825. )
  826. return out
  827. @dygraph_only
  828. def fill_(x, value):
  829. """
  830. **Notes**:
  831. **This API is ONLY available in Dygraph mode**
  832. This function fill the Tensor with value inplace.
  833. Args:
  834. x (Tensor): ``x`` is the Tensor we want to filled data inplace
  835. value (Scale): ``value`` is the value to be filled in x
  836. Returns:
  837. x(Tensor), Tensor x filled with value inplace
  838. Examples:
  839. .. code-block:: python
  840. >>> import paddle
  841. >>> tensor = paddle.to_tensor([0, 1, 2, 3, 4])
  842. >>> tensor.fill_(0)
  843. >>> print(tensor.tolist())
  844. [0, 0, 0, 0, 0]
  845. """
  846. if not isinstance(value, (float, int)):
  847. raise TypeError(
  848. "The type of 'value' must be int or float, but received %s."
  849. % (type(value))
  850. )
  851. return _C_ops.fill_(x, value)
  852. @dygraph_only
  853. def zero_(x):
  854. """
  855. **Notes**:
  856. **This API is ONLY available in Dygraph mode**
  857. This function fill the Tensor with zero inplace.
  858. Args:
  859. x (Tensor): ``x`` is the Tensor we want to filled with zero inplace
  860. Returns:
  861. x (Tensor), Tensor x filled with zero inplace
  862. Examples:
  863. .. code-block:: python
  864. >>> import paddle
  865. >>> tensor = paddle.to_tensor([0, 1, 2, 3, 4])
  866. >>> tensor.zero_()
  867. >>> print(tensor.tolist())
  868. [0, 0, 0, 0, 0]
  869. """
  870. return _C_ops.fill_(x, 0.0)
  871. @dygraph_only
  872. def fill_diagonal_(x, value, offset=0, wrap=False, name=None):
  873. """
  874. Note:
  875. This API is ONLY available in Dygraph mode.
  876. This function fill the value into the x Tensor's diagonal inplace.
  877. Args:
  878. x(Tensor): ``x`` is the original Tensor
  879. value(Scale): ``value`` is the value to filled in x
  880. offset(int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
  881. wrap(bool,optional): the diagonal 'wrapped' after N columns for tall matrices.
  882. name(str,optional): Name for the operation (optional, default is None)
  883. Returns:
  884. Tensor, Tensor with diagonal filled with value.
  885. Examples:
  886. .. code-block:: python
  887. >>> import paddle
  888. >>> x = paddle.ones((4, 3)) * 2
  889. >>> x.fill_diagonal_(1.0)
  890. >>> print(x.tolist())
  891. [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]
  892. """
  893. if in_dynamic_mode():
  894. if len(x.shape) == 2:
  895. return _C_ops.fill_diagonal_(x, value, offset, wrap)
  896. return _C_ops.fill_diagonal_(x, value, offset, True)
  897. def _fill_diagonal_tensor_impl(x, y, offset=0, dim1=0, dim2=1, inplace=False):
  898. inshape = x.shape
  899. assert dim1 < len(inshape) and dim1 >= -len(
  900. inshape
  901. ), 'dim1 should between [-rank,rank) in fill_diagonal_tensor_'
  902. assert dim2 < len(inshape) and dim2 >= -len(
  903. inshape
  904. ), 'dim2 should between [-rank,rank) in fill_diagonal_tensor_'
  905. assert len(inshape) >= 2, 'Tensor dims should >= 2 in fill_diagonal_tensor_'
  906. dim1 %= len(inshape)
  907. dim2 %= len(inshape)
  908. predshape = []
  909. for i in range(len(inshape)):
  910. if i != dim1 and i != dim2:
  911. predshape.append(inshape[i])
  912. diaglen = min(
  913. inshape[dim1],
  914. inshape[dim1] + offset,
  915. inshape[dim2],
  916. inshape[dim2] - offset,
  917. )
  918. predshape.append(diaglen)
  919. assert tuple(predshape) == tuple(
  920. y.shape
  921. ), f"the y shape should be {predshape}"
  922. if len(y.shape) == 1:
  923. y = y.reshape([1, -1])
  924. if in_dynamic_or_pir_mode():
  925. if inplace:
  926. return _C_ops.fill_diagonal_tensor_(x, y, offset, dim1, dim2)
  927. else:
  928. return _C_ops.fill_diagonal_tensor(x, y, offset, dim1, dim2)
  929. else:
  930. check_variable_and_dtype(
  931. x,
  932. 'X',
  933. [
  934. 'float16',
  935. 'float32',
  936. 'float64',
  937. 'uint16',
  938. 'uint8',
  939. 'int8',
  940. 'int16',
  941. 'int32',
  942. 'int64',
  943. 'bool',
  944. 'complex64',
  945. 'complex128',
  946. ],
  947. 'paddle.tensor.manipulation.fill_diagonal_tensor',
  948. )
  949. check_variable_and_dtype(
  950. y,
  951. 'Y',
  952. [
  953. 'float16',
  954. 'float32',
  955. 'float64',
  956. 'uint16',
  957. 'uint8',
  958. 'int8',
  959. 'int16',
  960. 'int32',
  961. 'int64',
  962. 'bool',
  963. 'complex64',
  964. 'complex128',
  965. ],
  966. 'paddle.tensor.manipulation.fill_diagonal_tensor',
  967. )
  968. helper = LayerHelper('fill_diagonal_tensor', **locals())
  969. out = helper.create_variable_for_type_inference(x.dtype)
  970. helper.append_op(
  971. type='fill_diagonal_tensor',
  972. inputs={
  973. 'X': x,
  974. 'Y': y,
  975. },
  976. outputs={'Out': out},
  977. attrs={
  978. 'offset': offset,
  979. 'dim1': dim1,
  980. 'dim2': dim2,
  981. },
  982. )
  983. return out
  984. def fill_diagonal_tensor_(x, y, offset=0, dim1=0, dim2=1, name=None):
  985. """
  986. Note:
  987. This API is ONLY available in Dygraph mode.
  988. This function fill the source Tensor y into the x Tensor's diagonal inplace.
  989. Args:
  990. x (Tensor): ``x`` is the original Tensor
  991. y (Tensor): ``y`` is the Tensor to filled in x
  992. dim1 (int,optional): first dimension with respect to which to fill diagonal. Default: 0.
  993. dim2 (int,optional): second dimension with respect to which to fill diagonal. Default: 1.
  994. offset (int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
  995. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  996. Returns:
  997. Tensor, Tensor with diagonal filled with y.
  998. Examples:
  999. .. code-block:: python
  1000. >>> import paddle
  1001. >>> x = paddle.ones((4, 3)) * 2
  1002. >>> y = paddle.ones((3,))
  1003. >>> x.fill_diagonal_tensor_(y)
  1004. >>> print(x.tolist())
  1005. [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]
  1006. """
  1007. return _fill_diagonal_tensor_impl(
  1008. x, y, offset=offset, dim1=dim1, dim2=dim2, inplace=True
  1009. )
  1010. def fill_diagonal_tensor(x, y, offset=0, dim1=0, dim2=1, name=None):
  1011. """
  1012. This function fill the source Tensor y into the x Tensor's diagonal.
  1013. Args:
  1014. x (Tensor): ``x`` is the original Tensor
  1015. y (Tensor): ``y`` is the Tensor to filled in x
  1016. dim1 (int,optional): first dimension with respect to which to fill diagonal. Default: 0.
  1017. dim2 (int,optional): second dimension with respect to which to fill diagonal. Default: 1.
  1018. offset (int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
  1019. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1020. Returns:
  1021. Tensor, Tensor with diagonal filled with y.
  1022. Examples:
  1023. .. code-block:: python
  1024. >>> import paddle
  1025. >>> x = paddle.ones((4, 3)) * 2
  1026. >>> y = paddle.ones((3,))
  1027. >>> nx = x.fill_diagonal_tensor(y)
  1028. >>> print(nx.tolist())
  1029. [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]
  1030. """
  1031. return _fill_diagonal_tensor_impl(
  1032. x, y, offset=offset, dim1=dim1, dim2=dim2, inplace=False
  1033. )
  1034. @dygraph_only
  1035. def tolist(x):
  1036. """
  1037. Note:
  1038. This API is ONLY available in Dygraph mode.
  1039. This function translate the paddle.Tensor to python list.
  1040. Args:
  1041. x (Tensor): ``x`` is the Tensor we want to translate to list.
  1042. Returns:
  1043. list, A list that contain the same value of current Tensor.
  1044. Examples:
  1045. .. code-block:: python
  1046. >>> import paddle
  1047. >>> t = paddle.to_tensor([0,1,2,3,4])
  1048. >>> expectlist = t.tolist()
  1049. >>> print(expectlist)
  1050. [0, 1, 2, 3, 4]
  1051. >>> expectlist = paddle.tolist(t)
  1052. >>> print(expectlist)
  1053. [0, 1, 2, 3, 4]
  1054. """
  1055. # TODO(zhouwei): will remove 0-D Tensor.numpy() hack
  1056. return x.numpy(False).tolist()
  1057. def concat(x, axis=0, name=None):
  1058. """
  1059. Concatenates the input along the axis. It doesn't support 0-D Tensor because it requires a certain axis, and 0-D Tensor
  1060. doesn't have any axis.
  1061. Args:
  1062. x (list|tuple): ``x`` is a Tensor list or Tensor tuple which is with data type bool, float16, bfloat16,
  1063. float32, float64, int8, int16, int32, int64, uint8, uint16, complex64, complex128. All the Tensors in ``x`` must have same data type.
  1064. axis (int|Tensor, optional): Specify the axis to operate on the input Tensors.
  1065. Tt should be integer or 0-D int Tensor with shape []. The effective range is [-R, R), where R is Rank(x). When ``axis < 0``,
  1066. it works the same way as ``axis+R``. Default is 0.
  1067. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1068. Returns:
  1069. Tensor, A Tensor with the same data type as ``x``.
  1070. Examples:
  1071. .. code-block:: python
  1072. >>> import paddle
  1073. >>> x1 = paddle.to_tensor([[1, 2, 3],
  1074. ... [4, 5, 6]])
  1075. >>> x2 = paddle.to_tensor([[11, 12, 13],
  1076. ... [14, 15, 16]])
  1077. >>> x3 = paddle.to_tensor([[21, 22],
  1078. ... [23, 24]])
  1079. >>> zero = paddle.full(shape=[1], dtype='int32', fill_value=0)
  1080. >>> # When the axis is negative, the real axis is (axis + Rank(x))
  1081. >>> # As follow, axis is -1, Rank(x) is 2, the real axis is 1
  1082. >>> out1 = paddle.concat(x=[x1, x2, x3], axis=-1)
  1083. >>> out2 = paddle.concat(x=[x1, x2], axis=0)
  1084. >>> out3 = paddle.concat(x=[x1, x2], axis=zero)
  1085. >>> print(out1)
  1086. Tensor(shape=[2, 8], dtype=int64, place=Place(cpu), stop_gradient=True,
  1087. [[1 , 2 , 3 , 11, 12, 13, 21, 22],
  1088. [4 , 5 , 6 , 14, 15, 16, 23, 24]])
  1089. >>> print(out2)
  1090. Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  1091. [[1 , 2 , 3 ],
  1092. [4 , 5 , 6 ],
  1093. [11, 12, 13],
  1094. [14, 15, 16]])
  1095. >>> print(out3)
  1096. Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  1097. [[1 , 2 , 3 ],
  1098. [4 , 5 , 6 ],
  1099. [11, 12, 13],
  1100. [14, 15, 16]])
  1101. """
  1102. input = x
  1103. if in_dynamic_mode():
  1104. if isinstance(axis, Variable):
  1105. axis = axis.item(0)
  1106. if not isinstance(input, (Variable, paddle.pir.Value)):
  1107. input = [t for t in input if t.shape.count(0) == 0]
  1108. return _C_ops.concat(input, axis)
  1109. elif in_pir_mode():
  1110. if isinstance(input, paddle.pir.Value):
  1111. assert input.is_dense_tensor_array_type(), (
  1112. "If the element of concat op is Value, "
  1113. "dtype of the element must be Tensorarray"
  1114. )
  1115. out, _ = _C_ops.array_to_tensor(input, axis, False)
  1116. return out
  1117. if not isinstance(input, paddle.pir.Value):
  1118. input = [t for t in input if t.shape.count(0) == 0]
  1119. return _C_ops.concat(input, axis)
  1120. else:
  1121. check_type(input, 'input', (list, tuple, Variable), 'concat')
  1122. if not isinstance(input, Variable):
  1123. for id, x in enumerate(input):
  1124. check_variable_and_dtype(
  1125. x,
  1126. 'input[' + str(id) + ']',
  1127. [
  1128. 'bool',
  1129. 'float16',
  1130. 'bfloat16',
  1131. 'float32',
  1132. 'float64',
  1133. 'int16',
  1134. 'int32',
  1135. 'int64',
  1136. 'int8',
  1137. 'unit8',
  1138. 'uint16',
  1139. 'complex64',
  1140. 'complex128',
  1141. ],
  1142. 'concat',
  1143. )
  1144. if x.dtype != input[0].dtype:
  1145. raise TypeError(
  1146. "All the Tensors in the input must have the same data type."
  1147. )
  1148. else:
  1149. input = [input]
  1150. check_type(axis, 'axis', (int, Variable), 'concat')
  1151. if isinstance(axis, Variable):
  1152. check_dtype(
  1153. axis.dtype,
  1154. 'axis',
  1155. ['int32', 'int64'],
  1156. 'concat',
  1157. "The data type of axis must be int32 or int64 when axis is a Tensor",
  1158. )
  1159. helper = LayerHelper('concat', **locals())
  1160. out = helper.create_variable_for_type_inference(
  1161. dtype=helper.input_dtype()
  1162. )
  1163. if input[0].desc.type() == core.VarDesc.VarType.LOD_TENSOR_ARRAY:
  1164. # NOTE(liym27): Don't remove this if branch!
  1165. # This feature is supported for Dynamic-to-Static, because after transformed, the type of inputs[0]
  1166. # is LOD_TENSOR_ARRAY in some scenarios. And this feature can be used in static graph mode.
  1167. assert len(input) == 1, (
  1168. "If the elements of 'input' in concat are Variable(LoDTensorArray), "
  1169. "number of the elements must be 1, but received %s."
  1170. % len(input)
  1171. )
  1172. out_index = helper.create_variable_for_type_inference(dtype="int32")
  1173. helper.append_op(
  1174. type='tensor_array_to_tensor',
  1175. inputs={'X': input[0]},
  1176. outputs={'Out': [out], 'OutIndex': [out_index]},
  1177. attrs={'axis': axis, 'use_stack': False},
  1178. )
  1179. else:
  1180. inputs = {'X': input}
  1181. attrs = {}
  1182. if isinstance(axis, Variable):
  1183. axis.stop_gradient = True
  1184. inputs['AxisTensor'] = axis
  1185. else:
  1186. attrs['axis'] = axis
  1187. helper.append_op(
  1188. type='concat',
  1189. inputs=inputs,
  1190. outputs={'Out': [out]},
  1191. attrs=attrs,
  1192. )
  1193. return out
  1194. def broadcast_tensors(input, name=None):
  1195. """
  1196. Broadcast a list of tensors following broadcast semantics
  1197. Note:
  1198. If you want know more about broadcasting, please refer to `Introduction to Tensor`_ .
  1199. .. _Introduction to Tensor: ../../guides/beginner/tensor_en.html#chapter5-broadcasting-of-tensor
  1200. Args:
  1201. input (list|tuple): ``input`` is a Tensor list or Tensor tuple which is with data type bool,
  1202. float16, float32, float64, int32, int64, complex64, complex128. All the Tensors in ``input`` must have same data type.
  1203. Currently we only support tensors with rank no greater than 5.
  1204. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1205. Returns:
  1206. list(Tensor), The list of broadcasted tensors following the same order as ``input``.
  1207. Examples:
  1208. .. code-block:: python
  1209. >>> import paddle
  1210. >>> x1 = paddle.rand([1, 2, 3, 4]).astype('float32')
  1211. >>> x2 = paddle.rand([1, 2, 1, 4]).astype('float32')
  1212. >>> x3 = paddle.rand([1, 1, 3, 1]).astype('float32')
  1213. >>> out1, out2, out3 = paddle.broadcast_tensors(input=[x1, x2, x3])
  1214. >>> # out1, out2, out3: tensors broadcasted from x1, x2, x3 with shape [1,2,3,4]
  1215. """
  1216. num_inputs = len(input)
  1217. if in_dynamic_or_pir_mode():
  1218. return _C_ops.broadcast_tensors(input)
  1219. else:
  1220. check_type(input, 'input', (list, tuple), 'broadcast_tensors')
  1221. if num_inputs < 1:
  1222. raise TypeError(
  1223. "At least 1 tensor is needed to perform broadcast_tensors"
  1224. )
  1225. # Check input types
  1226. for id, x in enumerate(input):
  1227. check_variable_and_dtype(
  1228. x,
  1229. 'input[' + str(id) + ']',
  1230. [
  1231. 'bool',
  1232. 'float16',
  1233. 'float32',
  1234. 'float64',
  1235. 'int32',
  1236. 'int64',
  1237. 'uint16',
  1238. 'complex64',
  1239. 'complex128',
  1240. ],
  1241. 'broadcast_tensors',
  1242. )
  1243. if x.dtype != input[0].dtype:
  1244. raise TypeError(
  1245. "All the Tensors in the input must have the same data type."
  1246. )
  1247. # Check bcast semantics
  1248. output_shape_r_last_tensor_index = []
  1249. output_shape_r = []
  1250. # Use while loop due to weird behaviour of "range()"
  1251. j = 0
  1252. while j < len(input):
  1253. tensor = input[j]
  1254. shape = list(reversed(tensor.shape))
  1255. i = 0
  1256. while i < len(shape):
  1257. if len(output_shape_r) <= i:
  1258. output_shape_r.append(shape[i])
  1259. output_shape_r_last_tensor_index.append(j)
  1260. else:
  1261. invalid = (
  1262. output_shape_r[i] != shape[i]
  1263. and output_shape_r[i] != 1
  1264. and shape[i] != 1
  1265. )
  1266. if invalid:
  1267. last_index = output_shape_r_last_tensor_index[i]
  1268. raise TypeError(
  1269. "Input tensors to broadcast_tensors does not follow bcast semantics"
  1270. f"Tensor {last_index} conflicts with Tensor {j} in reversed dimension {i}"
  1271. )
  1272. if output_shape_r[i] <= shape[i]:
  1273. output_shape_r[i] = shape[i]
  1274. output_shape_r_last_tensor_index[i] = j
  1275. i += 1 # while i < len(shape)
  1276. j += 1 # while j < len(input)
  1277. helper = LayerHelper('broadcast_tensors', **locals())
  1278. i = 0
  1279. out = []
  1280. while i < num_inputs:
  1281. out.append(
  1282. helper.create_variable_for_type_inference(
  1283. dtype=helper.input_dtype()
  1284. )
  1285. )
  1286. i += 1
  1287. inputs = {'X': input}
  1288. helper.append_op(
  1289. type='broadcast_tensors',
  1290. inputs=inputs,
  1291. outputs={'Out': out},
  1292. attrs={},
  1293. )
  1294. return out
  1295. def flip(x, axis, name=None):
  1296. """
  1297. Reverse the order of a n-D tensor along given axis in axis.
  1298. Args:
  1299. x (Tensor): A Tensor(or LoDTensor) with shape :math:`[N_1, N_2,..., N_k]` . The data type of the input Tensor x
  1300. should be float32, float64, int32, int64, bool.
  1301. axis (list|tuple|int): The axis(axes) to flip on. Negative indices for indexing from the end are accepted.
  1302. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1303. Returns:
  1304. Tensor, Tensor or LoDTensor calculated by flip layer. The data type is same with input x.
  1305. Examples:
  1306. .. code-block:: python
  1307. >>> import paddle
  1308. >>> image_shape=(3, 2, 2)
  1309. >>> img = paddle.arange(image_shape[0] * image_shape[1] * image_shape[2]).reshape(image_shape)
  1310. >>> tmp = paddle.flip(img, [0,1])
  1311. >>> print(tmp)
  1312. Tensor(shape=[3, 2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
  1313. [[[10, 11],
  1314. [8 , 9 ]],
  1315. [[6 , 7 ],
  1316. [4 , 5 ]],
  1317. [[2 , 3 ],
  1318. [0 , 1 ]]])
  1319. >>> out = paddle.flip(tmp,-1)
  1320. >>> print(out)
  1321. Tensor(shape=[3, 2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
  1322. [[[11, 10],
  1323. [9 , 8 ]],
  1324. [[7 , 6 ],
  1325. [5 , 4 ]],
  1326. [[3 , 2 ],
  1327. [1 , 0 ]]])
  1328. """
  1329. if isinstance(axis, int):
  1330. axis = [axis]
  1331. if in_dynamic_or_pir_mode():
  1332. return _C_ops.flip(x, axis)
  1333. else:
  1334. helper = LayerHelper("flip", **locals())
  1335. check_type(x, 'X', (Variable), 'flip')
  1336. dtype = helper.input_dtype('x')
  1337. check_dtype(
  1338. dtype,
  1339. 'X',
  1340. ['float16', 'float32', 'float64', 'int32', 'int64', 'bool'],
  1341. 'flip',
  1342. )
  1343. check_type(axis, 'axis', (list, tuple), 'flip')
  1344. if name is None:
  1345. out = helper.create_variable_for_type_inference(dtype)
  1346. else:
  1347. out = helper.create_variable(
  1348. name=name, dtype=dtype, persistable=False
  1349. )
  1350. helper.append_op(
  1351. type="flip",
  1352. inputs={"X": x},
  1353. outputs={"Out": out},
  1354. attrs={"axis": axis},
  1355. )
  1356. return out
  1357. def rot90(x, k=1, axes=[0, 1], name=None):
  1358. """
  1359. Rotate a n-D tensor by 90 degrees. The rotation direction and times are specified by axes and the absolute value of k. Rotation direction is from axes[0] towards axes[1] if k > 0, and from axes[1] towards axes[0] for k < 0.
  1360. Args:
  1361. x (Tensor): The input Tensor(or LoDTensor). The data type of the input Tensor x
  1362. should be float16, float32, float64, int32, int64, bool. float16 is only supported on gpu.
  1363. k (int, optional): Direction and number of times to rotate, default value: 1.
  1364. axes (list|tuple, optional): Axes to rotate, dimension must be 2. default value: [0, 1].
  1365. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  1366. For more information, please refer to :ref:`api_guide_Name` .
  1367. Returns:
  1368. Tensor, Tensor or LoDTensor calculated by rot90 layer. The data type is same with input x.
  1369. Examples:
  1370. .. code-block:: python
  1371. >>> import paddle
  1372. >>> data = paddle.arange(4)
  1373. >>> data = paddle.reshape(data, (2, 2))
  1374. >>> print(data.numpy())
  1375. [[0 1]
  1376. [2 3]]
  1377. >>> y = paddle.rot90(data, 1, [0, 1])
  1378. >>> print(y.numpy())
  1379. [[1 3]
  1380. [0 2]]
  1381. >>> y= paddle.rot90(data, -1, [0, 1])
  1382. >>> print(y.numpy())
  1383. [[2 0]
  1384. [3 1]]
  1385. >>> data2 = paddle.arange(8)
  1386. >>> data2 = paddle.reshape(data2, (2,2,2))
  1387. >>> print(data2.numpy())
  1388. [[[0 1]
  1389. [2 3]]
  1390. [[4 5]
  1391. [6 7]]]
  1392. >>> y = paddle.rot90(data2, 1, [1, 2])
  1393. >>> print(y.numpy())
  1394. [[[1 3]
  1395. [0 2]]
  1396. [[5 7]
  1397. [4 6]]]
  1398. """
  1399. helper = LayerHelper("rot90", **locals())
  1400. check_type(x, 'X', (Variable, paddle.pir.Value), 'rot90')
  1401. dtype = helper.input_dtype('x')
  1402. check_dtype(
  1403. dtype,
  1404. 'X',
  1405. ['float16', 'float32', 'float64', 'int32', 'int64', 'bool'],
  1406. 'rot90',
  1407. )
  1408. check_type(axes, 'axes', (list, tuple), 'rot90')
  1409. input_total_dims = len(x.shape)
  1410. total_rot_dims = len(axes)
  1411. if total_rot_dims != 2:
  1412. raise ValueError(
  1413. f"expected total rotation axes == 2, but got axes = {total_rot_dims}"
  1414. )
  1415. if input_total_dims < 2:
  1416. raise ValueError(
  1417. f"expected total dims >= 2, but got total dims = {input_total_dims}"
  1418. )
  1419. if not (axes[0] != axes[1] and abs(axes[0] - axes[1]) != input_total_dims):
  1420. raise ValueError(
  1421. f"expected rotation axes to be different, but got axis0 = {axes[0]}, and axis1 = {axes[1]}"
  1422. )
  1423. if not (axes[0] < input_total_dims and axes[0] >= -input_total_dims):
  1424. raise ValueError(f"Rotation axis0 out of range, axis0 = {axes[0]}")
  1425. if not (axes[1] < input_total_dims and axes[1] >= -input_total_dims):
  1426. raise ValueError(f"Rotation axis1 out of range, axis1 = {axes[1]}")
  1427. k %= 4
  1428. if k == 0:
  1429. return x
  1430. if k == 2:
  1431. return flip(flip(x, axes[0]), axes[1])
  1432. axes_list = list(range(0, input_total_dims))
  1433. (axes_list[axes[0]], axes_list[axes[1]]) = (
  1434. axes_list[axes[1]],
  1435. axes_list[axes[0]],
  1436. )
  1437. if k == 1:
  1438. return transpose(flip(x, axes[1]), axes_list)
  1439. else:
  1440. # k == 3
  1441. return flip(transpose(x, axes_list), axes[1])
  1442. def flatten(x, start_axis=0, stop_axis=-1, name=None):
  1443. r"""
  1444. Flattens a contiguous range of axes in a tensor according to start_axis and stop_axis.
  1445. Note:
  1446. The output Tensor will share data with origin Tensor and doesn't have a Tensor copy in ``dygraph`` mode.
  1447. If you want to use the Tensor copy version, please use `Tensor.clone` like ``flatten_clone_x = x.flatten().clone()``.
  1448. For Example:
  1449. .. code-block:: text
  1450. Case 1:
  1451. Given
  1452. X.shape = (3, 100, 100, 4)
  1453. and
  1454. start_axis = 1
  1455. end_axis = 2
  1456. We get:
  1457. Out.shape = (3, 100 * 100, 4)
  1458. Case 2:
  1459. Given
  1460. X.shape = (3, 100, 100, 4)
  1461. and
  1462. start_axis = 0
  1463. stop_axis = -1
  1464. We get:
  1465. Out.shape = (3 * 100 * 100 * 4)
  1466. Args:
  1467. x (Tensor): A tensor of number of dimensions >= axis. A tensor with data type float16, float32,
  1468. float64, int8, int32, int64, uint8.
  1469. start_axis (int): the start axis to flatten
  1470. stop_axis (int): the stop axis to flatten
  1471. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1472. Returns:
  1473. Tensor, A tensor with the contents of the input tensor, whose input axes are flattened by indicated :attr:`start_axis` and :attr:`end_axis`, and data type is the same as input :attr:`x`.
  1474. Examples:
  1475. .. code-block:: python
  1476. >>> import paddle
  1477. >>> image_shape=(2, 3, 4, 4)
  1478. >>> x = paddle.arange(end=image_shape[0] * image_shape[1] * image_shape[2] * image_shape[3])
  1479. >>> img = paddle.reshape(x, image_shape)
  1480. >>> out = paddle.flatten(img, start_axis=1, stop_axis=2)
  1481. >>> print(out.shape)
  1482. [2, 12, 4]
  1483. >>> # out shares data with img in dygraph mode
  1484. >>> img[0, 0, 0, 0] = -1
  1485. >>> print(out[0, 0, 0])
  1486. Tensor(shape=[], dtype=int64, place=Place(cpu), stop_gradient=True,
  1487. -1)
  1488. """
  1489. if not (isinstance(x, (Variable, paddle.pir.Value))):
  1490. raise ValueError("The input x should be a Tensor")
  1491. x_dim = len(x.shape)
  1492. if x_dim == 0:
  1493. if not (isinstance(start_axis, int)) or start_axis not in [0, -1]:
  1494. raise ValueError(
  1495. "The start_axis should be int, and should be 0 or -1 when the input tensor is a 0-D-Tensor"
  1496. )
  1497. if not (isinstance(stop_axis, int)) or stop_axis not in [0, -1]:
  1498. raise ValueError(
  1499. "The stop_axis should be int, and should be 0 or -1 when the input tensor is a 0-D-Tensor"
  1500. )
  1501. else:
  1502. if (
  1503. not (isinstance(start_axis, int))
  1504. or (start_axis > x_dim - 1)
  1505. or start_axis < -x_dim
  1506. ):
  1507. raise ValueError(
  1508. "The start_axis should be a int, and in range [-rank(x), rank(x))"
  1509. )
  1510. if (
  1511. not (isinstance(stop_axis, int))
  1512. or (stop_axis > x_dim - 1)
  1513. or stop_axis < -x_dim
  1514. ):
  1515. raise ValueError(
  1516. "The stop_axis should be a int, and in range [-rank(x), rank(x))"
  1517. )
  1518. if start_axis < 0:
  1519. start_axis = start_axis + x_dim
  1520. if stop_axis < 0:
  1521. stop_axis = stop_axis + x_dim
  1522. if start_axis > stop_axis:
  1523. raise ValueError("The stop_axis should be larger than stat_axis")
  1524. if in_dynamic_or_pir_mode():
  1525. return _C_ops.flatten(x, start_axis, stop_axis)
  1526. else:
  1527. check_variable_and_dtype(
  1528. x,
  1529. 'x',
  1530. [
  1531. 'float16',
  1532. 'float32',
  1533. 'float64',
  1534. 'int8',
  1535. 'int16',
  1536. 'int32',
  1537. 'int64',
  1538. 'uint8',
  1539. 'uint16',
  1540. ],
  1541. 'flatten',
  1542. )
  1543. helper = LayerHelper('flatten', **locals())
  1544. out = helper.create_variable_for_type_inference(x.dtype)
  1545. x_shape = helper.create_variable_for_type_inference(x.dtype)
  1546. helper.append_op(
  1547. type='flatten_contiguous_range',
  1548. inputs={"X": x},
  1549. outputs={'Out': out, 'XShape': x_shape},
  1550. attrs={"start_axis": start_axis, "stop_axis": stop_axis},
  1551. )
  1552. return out
  1553. @inplace_apis_in_dygraph_only
  1554. def flatten_(x, start_axis=0, stop_axis=-1, name=None):
  1555. """
  1556. Inplace version of ``flatten`` API, the output Tensor will be inplaced with input ``x``.
  1557. Please refer to :ref:`api_paddle_flatten`.
  1558. """
  1559. if not (isinstance(x, Variable)):
  1560. raise ValueError("The input x should be a Tensor")
  1561. x_dim = len(x.shape)
  1562. if (
  1563. not (isinstance(start_axis, int))
  1564. or (start_axis > x_dim - 1)
  1565. or start_axis < -x_dim
  1566. ):
  1567. raise ValueError(
  1568. "The start_axis should be a int, and in range [-rank(x), rank(x))"
  1569. )
  1570. if (
  1571. not (isinstance(stop_axis, int))
  1572. or (stop_axis > x_dim - 1)
  1573. or stop_axis < -x_dim
  1574. ):
  1575. raise ValueError(
  1576. "The stop_axis should be a int, and in range [-rank(x), rank(x))"
  1577. )
  1578. if start_axis < 0:
  1579. start_axis = start_axis + x_dim
  1580. if stop_axis < 0:
  1581. stop_axis = stop_axis + x_dim
  1582. if start_axis > stop_axis:
  1583. raise ValueError("The stop_axis should be larger than stat_axis")
  1584. if in_dynamic_mode():
  1585. return _C_ops.flatten_(x, start_axis, stop_axis)
  1586. def roll(x, shifts, axis=None, name=None):
  1587. """
  1588. Roll the `x` tensor along the given axis(axes). With specific 'shifts', Elements that
  1589. roll beyond the last position are re-introduced at the first according to 'shifts'.
  1590. If a axis is not specified,
  1591. the tensor will be flattened before rolling and then restored to the original shape.
  1592. Args:
  1593. x (Tensor): The x tensor as input.
  1594. shifts (int|list|tuple): The number of places by which the elements
  1595. of the `x` tensor are shifted.
  1596. axis (int|list|tuple, optional): axis(axes) along which to roll. Default: None
  1597. name(str, optional): The default value is None. Normally there is no need for user to set this property.
  1598. For more information, please refer to :ref:`api_guide_Name` .
  1599. Returns:
  1600. Tensor, A Tensor with same data type as `x`.
  1601. Examples:
  1602. .. code-block:: python
  1603. >>> import paddle
  1604. >>> x = paddle.to_tensor([[1.0, 2.0, 3.0],
  1605. ... [4.0, 5.0, 6.0],
  1606. ... [7.0, 8.0, 9.0]])
  1607. >>> out_z1 = paddle.roll(x, shifts=1)
  1608. >>> print(out_z1.numpy())
  1609. [[9. 1. 2.]
  1610. [3. 4. 5.]
  1611. [6. 7. 8.]]
  1612. >>> out_z2 = paddle.roll(x, shifts=1, axis=0)
  1613. >>> print(out_z2.numpy())
  1614. [[7. 8. 9.]
  1615. [1. 2. 3.]
  1616. [4. 5. 6.]]
  1617. >>> out_z3 = paddle.roll(x, shifts=1, axis=1)
  1618. >>> print(out_z3.numpy())
  1619. [[3. 1. 2.]
  1620. [6. 4. 5.]
  1621. [9. 7. 8.]]
  1622. """
  1623. origin_shape = x.shape
  1624. if type(shifts) == int:
  1625. shifts = [shifts]
  1626. if type(axis) == int:
  1627. axis = [axis]
  1628. len_origin_shape = len(origin_shape)
  1629. if axis is not None:
  1630. for i in range(len(axis)):
  1631. if axis[i] >= len_origin_shape or axis[i] < -len_origin_shape:
  1632. raise ValueError(
  1633. f"axis is out of range, it should be in range [{-len_origin_shape}, {len_origin_shape}), but received {axis}"
  1634. )
  1635. else:
  1636. axis = []
  1637. if in_dynamic_or_pir_mode():
  1638. return _C_ops.roll(x, shifts, axis)
  1639. else:
  1640. check_variable_and_dtype(
  1641. x,
  1642. 'dtype',
  1643. [
  1644. 'float16',
  1645. 'float32',
  1646. 'uint16',
  1647. 'float64',
  1648. 'int32',
  1649. 'int64',
  1650. 'complex64',
  1651. 'complex128',
  1652. ],
  1653. 'roll',
  1654. )
  1655. helper = LayerHelper("roll", **locals())
  1656. check_type(axis, 'axis', (list, tuple), 'roll')
  1657. out = helper.create_variable_for_type_inference(x.dtype)
  1658. if isinstance(shifts, Variable):
  1659. helper.append_op(
  1660. type='roll',
  1661. inputs={'X': x, "ShiftsTensor": shifts},
  1662. outputs={'Out': out},
  1663. attrs={'axis': axis},
  1664. )
  1665. else:
  1666. check_type(shifts, 'shifts', (list, tuple), 'roll')
  1667. helper.append_op(
  1668. type='roll',
  1669. inputs={'X': x},
  1670. outputs={'Out': out},
  1671. attrs={'axis': axis, 'shifts': shifts},
  1672. )
  1673. return out
  1674. def stack(x, axis=0, name=None):
  1675. """
  1676. Stacks all the input tensors ``x`` along ``axis`` dimension.
  1677. All tensors must be of the same shape and same dtype.
  1678. For example, given N tensors of shape [A, B], if ``axis == 0``, the shape of stacked
  1679. tensor is [N, A, B]; if ``axis == 1``, the shape of stacked
  1680. tensor is [A, N, B], etc.
  1681. .. code-block:: text
  1682. Case 1:
  1683. Input:
  1684. x[0].shape = [1, 2]
  1685. x[0].data = [ [1.0 , 2.0 ] ]
  1686. x[1].shape = [1, 2]
  1687. x[1].data = [ [3.0 , 4.0 ] ]
  1688. x[2].shape = [1, 2]
  1689. x[2].data = [ [5.0 , 6.0 ] ]
  1690. Attrs:
  1691. axis = 0
  1692. Output:
  1693. Out.dims = [3, 1, 2]
  1694. Out.data =[ [ [1.0, 2.0] ],
  1695. [ [3.0, 4.0] ],
  1696. [ [5.0, 6.0] ] ]
  1697. Case 2:
  1698. Input:
  1699. x[0].shape = [1, 2]
  1700. x[0].data = [ [1.0 , 2.0 ] ]
  1701. x[1].shape = [1, 2]
  1702. x[1].data = [ [3.0 , 4.0 ] ]
  1703. x[2].shape = [1, 2]
  1704. x[2].data = [ [5.0 , 6.0 ] ]
  1705. Attrs:
  1706. axis = 1 or axis = -2 # If axis = -2, axis = axis+ndim(x[0])+1 = -2+2+1 = 1.
  1707. Output:
  1708. Out.shape = [1, 3, 2]
  1709. Out.data =[ [ [1.0, 2.0]
  1710. [3.0, 4.0]
  1711. [5.0, 6.0] ] ]
  1712. Args:
  1713. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x``
  1714. must be of the same shape and dtype. Supported data types: float32, float64, int32, int64.
  1715. axis (int, optional): The axis along which all inputs are stacked. ``axis`` range is ``[-(R+1), R+1)``,
  1716. where ``R`` is the number of dimensions of the first input tensor ``x[0]``.
  1717. If ``axis < 0``, ``axis = axis+R+1``. The default value of axis is 0.
  1718. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1719. Returns:
  1720. Tensor, The stacked tensor with same data type as input.
  1721. Examples:
  1722. .. code-block:: python
  1723. >>> import paddle
  1724. >>> x1 = paddle.to_tensor([[1.0, 2.0]])
  1725. >>> x2 = paddle.to_tensor([[3.0, 4.0]])
  1726. >>> x3 = paddle.to_tensor([[5.0, 6.0]])
  1727. >>> out = paddle.stack([x1, x2, x3], axis=0)
  1728. >>> print(out.shape)
  1729. [3, 1, 2]
  1730. >>> print(out)
  1731. Tensor(shape=[3, 1, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1732. [[[1., 2.]],
  1733. [[3., 4.]],
  1734. [[5., 6.]]])
  1735. >>> out = paddle.stack([x1, x2, x3], axis=-2)
  1736. >>> print(out.shape)
  1737. [1, 3, 2]
  1738. >>> print(out)
  1739. Tensor(shape=[1, 3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1740. [[[1., 2.],
  1741. [3., 4.],
  1742. [5., 6.]]])
  1743. """
  1744. axis = 0 if axis is None else axis
  1745. if in_dynamic_mode():
  1746. return _C_ops.stack(x, axis)
  1747. if not isinstance(x, list) and not isinstance(x, tuple):
  1748. # NOTE:(zhiqiu) Only support Variable as input if the Variable is a LOD_TENSOR_ARRAY create by create_array, array_write, array_read, etc.
  1749. # In that case, Variable is array of tensors indeed.
  1750. if (
  1751. isinstance(x, Variable)
  1752. and x.desc.type() == core.VarDesc.VarType.LOD_TENSOR_ARRAY
  1753. ) or (
  1754. isinstance(x, paddle.pir.Value) and x.is_dense_tensor_array_type()
  1755. ):
  1756. x = [x]
  1757. else:
  1758. raise TypeError(
  1759. "The type of '{}' in {} must be {}, but received {}".format(
  1760. 'x',
  1761. 'stack',
  1762. 'list[Tensor], tuple[Tensor] or TensorArray',
  1763. type(x),
  1764. )
  1765. )
  1766. if in_pir_mode():
  1767. if x[0].is_dense_tensor_array_type():
  1768. assert len(x) == 1, (
  1769. "If the elements of 'x' in stack are Variable(LoDTensorArray), "
  1770. "number of the elements must be 1, but received %s." % len(x)
  1771. )
  1772. out, _ = _C_ops.array_to_tensor(x, axis, True)
  1773. return out
  1774. else:
  1775. return _C_ops.stack(x, axis)
  1776. helper = LayerHelper('stack', **locals())
  1777. out = helper.create_variable_for_type_inference(x[0].dtype)
  1778. if x[0].desc.type() == core.VarDesc.VarType.LOD_TENSOR_ARRAY:
  1779. assert len(x) == 1, (
  1780. "If the elements of 'x' in stack are Variable(LoDTensorArray), "
  1781. "number of the elements must be 1, but received %s." % len(x)
  1782. )
  1783. out_index = helper.create_variable_for_type_inference(dtype="int32")
  1784. for i in x:
  1785. check_variable_and_dtype(
  1786. i,
  1787. 'x',
  1788. [
  1789. 'float16',
  1790. 'float32',
  1791. 'float64',
  1792. 'int32',
  1793. 'int64',
  1794. 'uint16',
  1795. ],
  1796. 'stack',
  1797. )
  1798. helper.append_op(
  1799. type='tensor_array_to_tensor',
  1800. inputs={'X': x[0]},
  1801. outputs={'Out': [out], 'OutIndex': [out_index]},
  1802. attrs={'axis': axis, 'use_stack': True},
  1803. )
  1804. else:
  1805. helper.append_op(
  1806. type='stack',
  1807. inputs={'X': x},
  1808. outputs={'Y': out},
  1809. attrs={'axis': axis},
  1810. )
  1811. return out
  1812. def hstack(x, name=None):
  1813. """
  1814. Stacks all the input tensors ``x`` along horizontal axis.
  1815. All tensors must be of the same dtype.
  1816. Args:
  1817. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x`` must be of the same
  1818. shape and dtype. Supported data types: ``float16``, ``float32``, ``float64``, ``int8``, ``int32``, ``int64`` or ``bfloat16``.
  1819. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1820. Returns:
  1821. Tensor, The stacked tensor with same data type as input.
  1822. Examples:
  1823. .. code-block:: python
  1824. >>> import paddle
  1825. >>> # hstack with 0-D tensors
  1826. >>> x1 = paddle.to_tensor(1.0)
  1827. >>> x2 = paddle.to_tensor(2.0)
  1828. >>> out = paddle.hstack((x1, x2))
  1829. >>> print(out)
  1830. Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1831. [1., 2.])
  1832. >>> # hstack with 1-D tensors
  1833. >>> x1 = paddle.to_tensor([1.0, 2.0])
  1834. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  1835. >>> out = paddle.hstack((x1, x2))
  1836. >>> print(out)
  1837. Tensor(shape=[5], dtype=float32, place=Place(cpu), stop_gradient=True,
  1838. [1., 2., 3., 4., 5.])
  1839. >>> # hstack mix with 0-D & 1-D tensors
  1840. >>> x1 = paddle.to_tensor(1.0)
  1841. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  1842. >>> out = paddle.hstack((x1, x2))
  1843. >>> print(out)
  1844. Tensor(shape=[4], dtype=float32, place=Place(cpu), stop_gradient=True,
  1845. [1., 3., 4., 5.])
  1846. >>> # hstack with 2-D tensors
  1847. >>> x1 = paddle.to_tensor([[1.0, 2.0]])
  1848. >>> x2 = paddle.to_tensor([[3.0, 4.0, 5.0]])
  1849. >>> out = paddle.hstack((x1, x2))
  1850. >>> print(out)
  1851. Tensor(shape=[1, 5], dtype=float32, place=Place(cpu), stop_gradient=True,
  1852. [[1., 2., 3., 4., 5.]])
  1853. """
  1854. arrays = paddle.atleast_1d(*x)
  1855. if not isinstance(arrays, list):
  1856. arrays = [arrays]
  1857. if arrays and arrays[0].ndim == 1:
  1858. return paddle.concat(arrays, axis=0, name=name)
  1859. else:
  1860. return paddle.concat(arrays, axis=1, name=name)
  1861. def vstack(x, name=None):
  1862. """
  1863. Stacks all the input tensors ``x`` along vertical axis.
  1864. All tensors must be of the same dtype.
  1865. Args:
  1866. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x`` must be of the same
  1867. shape and dtype. Supported data types: ``float16``, ``float32``, ``float64``, ``int8``, ``int32``, ``int64`` or ``bfloat16``.
  1868. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1869. Returns:
  1870. Tensor, The stacked tensor with same data type as input.
  1871. Examples:
  1872. .. code-block:: python
  1873. >>> import paddle
  1874. >>> # vstack with 0-D tensors
  1875. >>> x1 = paddle.to_tensor(1.0)
  1876. >>> x2 = paddle.to_tensor(2.0)
  1877. >>> out = paddle.vstack((x1, x2))
  1878. >>> print(out)
  1879. Tensor(shape=[2, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  1880. [[1.],
  1881. [2.]])
  1882. >>> # vstack with 1-D tensors
  1883. >>> x1 = paddle.to_tensor([1.0, 2.0, 3.0])
  1884. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  1885. >>> out = paddle.vstack((x1, x2))
  1886. >>> print(out)
  1887. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  1888. [[1., 2., 3.],
  1889. [3., 4., 5.]])
  1890. >>> # vstack mix with 1-D & 2-D tensors
  1891. >>> x1 = paddle.to_tensor([1.0, 2.0, 3.0])
  1892. >>> x2 = paddle.to_tensor([[3.0, 4.0, 5.0]])
  1893. >>> out = paddle.vstack((x1, x2))
  1894. >>> print(out)
  1895. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  1896. [[1., 2., 3.],
  1897. [3., 4., 5.]])
  1898. >>> # vstack with 2-D tensors
  1899. >>> x1 = paddle.to_tensor([[1.0, 2.0, 3.0]])
  1900. >>> x2 = paddle.to_tensor([[3.0, 4.0, 5.0]])
  1901. >>> out = paddle.vstack((x1, x2))
  1902. >>> print(out)
  1903. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  1904. [[1., 2., 3.],
  1905. [3., 4., 5.]])
  1906. """
  1907. arrays = paddle.atleast_2d(*x)
  1908. if not isinstance(arrays, list):
  1909. arrays = [arrays]
  1910. return paddle.concat(arrays, axis=0, name=name)
  1911. def dstack(x, name=None):
  1912. """
  1913. Stacks all the input tensors ``x`` along depth axis.
  1914. All tensors must be of the same dtype.
  1915. Args:
  1916. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x`` must be of the same
  1917. shape and dtype. Supported data types: ``float16``, ``float32``, ``float64``, ``int8``, ``int32``, ``int64`` or ``bfloat16``.
  1918. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1919. Returns:
  1920. Tensor, The stacked tensor with same data type as input.
  1921. Examples:
  1922. .. code-block:: python
  1923. >>> import paddle
  1924. >>> # dstack with 0-D tensors
  1925. >>> x1 = paddle.to_tensor(1.0)
  1926. >>> x2 = paddle.to_tensor(2.0)
  1927. >>> out = paddle.dstack((x1, x2))
  1928. >>> print(out)
  1929. Tensor(shape=[1, 1, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1930. [[[1., 2.]]])
  1931. >>> # dstack with 1-D tensors
  1932. >>> x1 = paddle.to_tensor([1.0, 2.0, 3.0])
  1933. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  1934. >>> out = paddle.dstack((x1, x2))
  1935. >>> print(out)
  1936. Tensor(shape=[1, 3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1937. [[[1., 3.],
  1938. [2., 4.],
  1939. [3., 5.]]])
  1940. >>> # dstack with 3-D tensors
  1941. >>> x1 = paddle.to_tensor([[[1.0, 2.0], [3.0, 4.0]]])
  1942. >>> x2 = paddle.to_tensor([[[3.0, 4.0], [5.0, 6.0]]])
  1943. >>> out = paddle.dstack((x1, x2))
  1944. >>> print(out)
  1945. Tensor(shape=[1, 2, 4], dtype=float32, place=Place(cpu), stop_gradient=True,
  1946. [[[1., 2., 3., 4.],
  1947. [3., 4., 5., 6.]]])
  1948. """
  1949. arrays = paddle.atleast_3d(*x)
  1950. if not isinstance(arrays, list):
  1951. arrays = [arrays]
  1952. return paddle.concat(arrays, axis=2, name=name)
  1953. def column_stack(x, name=None):
  1954. """
  1955. Stacks all the input tensors ``x`` along horizontal axis. Each tensor in ``x`` will be first reshaped into ``(tensor.numel(), 1)``
  1956. if ``tensor.ndim < 2`` before being stacked.
  1957. All tensors must be of the same dtype.
  1958. Args:
  1959. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x`` must be of the same
  1960. shape and dtype. Supported data types: ``float16``, ``float32``, ``float64``, ``int32``, ``int64`` or ``bfloat16``.
  1961. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  1962. Returns:
  1963. Tensor, The stacked tensor with same data type as input.
  1964. Examples:
  1965. .. code-block:: python
  1966. >>> import paddle
  1967. >>> # column_stack with 0-D tensors
  1968. >>> x1 = paddle.to_tensor(1.0)
  1969. >>> x2 = paddle.to_tensor(2.0)
  1970. >>> out = paddle.column_stack((x1, x2))
  1971. >>> print(out)
  1972. Tensor(shape=[1, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1973. [[1., 2.]])
  1974. >>> # column_stack mix with 1-D & 2-D tensors
  1975. >>> x1 = paddle.to_tensor([[1.0], [2.0], [3.0]])
  1976. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  1977. >>> out = paddle.column_stack((x1, x2))
  1978. >>> print(out)
  1979. Tensor(shape=[3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1980. [[1., 3.],
  1981. [2., 4.],
  1982. [3., 5.]])
  1983. >>> # column_stack with 3-D tensors
  1984. >>> x1 = paddle.to_tensor([[[1.0, 2.0], [3.0, 4.0]]])
  1985. >>> x2 = paddle.to_tensor([[[3.0, 4.0], [5.0, 6.0]]])
  1986. >>> out = paddle.column_stack((x1, x2))
  1987. >>> print(out)
  1988. Tensor(shape=[1, 4, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  1989. [[[1., 2.],
  1990. [3., 4.],
  1991. [3., 4.],
  1992. [5., 6.]]])
  1993. """
  1994. arrays = []
  1995. for tensor in x:
  1996. if tensor.ndim < 2:
  1997. arrays.append(tensor.reshape((tensor.numel(), 1)))
  1998. else:
  1999. arrays.append(tensor)
  2000. return paddle.concat(arrays, axis=1, name=name)
  2001. def row_stack(x, name=None):
  2002. """
  2003. Alias of `paddle.vstack()`.
  2004. Stacks all the input tensors ``x`` along vertical axis.
  2005. All tensors must be of the same dtype.
  2006. Args:
  2007. x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x`` must be of the same
  2008. shape and dtype. Supported data types: ``float16``, ``float32``, ``float64``, ``int8``, ``int32``, ``int64`` or ``bfloat16``.
  2009. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  2010. Returns:
  2011. Tensor, The stacked tensor with same data type as input.
  2012. Examples:
  2013. .. code-block:: python
  2014. >>> import paddle
  2015. >>> # row_stack with 0-D tensors
  2016. >>> x1 = paddle.to_tensor(1.0)
  2017. >>> x2 = paddle.to_tensor(2.0)
  2018. >>> out = paddle.row_stack((x1, x2))
  2019. >>> print(out)
  2020. Tensor(shape=[2, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  2021. [[1.],
  2022. [2.]])
  2023. >>> # row_stack with 1-D tensors
  2024. >>> x1 = paddle.to_tensor([1.0, 2.0, 3.0])
  2025. >>> x2 = paddle.to_tensor([3.0, 4.0, 5.0])
  2026. >>> out = paddle.row_stack((x1, x2))
  2027. >>> print(out)
  2028. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  2029. [[1., 2., 3.],
  2030. [3., 4., 5.]])
  2031. >>> # row_stack mix with 1-D & 2-D tensors
  2032. >>> x1 = paddle.to_tensor([1.0, 2.0, 3.0])
  2033. >>> x2 = paddle.to_tensor([[3.0, 4.0, 5.0]])
  2034. >>> out = paddle.row_stack((x1, x2))
  2035. >>> print(out)
  2036. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  2037. [[1., 2., 3.],
  2038. [3., 4., 5.]])
  2039. >>> # row_stack with 2-D tensors
  2040. >>> x1 = paddle.to_tensor([[1.0, 2.0, 3.0]])
  2041. >>> x2 = paddle.to_tensor([[3.0, 4.0, 5.0]])
  2042. >>> out = paddle.row_stack((x1, x2))
  2043. >>> print(out)
  2044. Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  2045. [[1., 2., 3.],
  2046. [3., 4., 5.]])
  2047. """
  2048. return paddle.vstack(x, name=name)
  2049. def split(x, num_or_sections, axis=0, name=None):
  2050. """
  2051. Split the input tensor into multiple sub-Tensors.
  2052. Args:
  2053. x (Tensor): A N-D Tensor. The data type is bool, bfloat16, float16, float32, float64, uint8, int8, int32 or int64.
  2054. num_or_sections (int|list|tuple): If ``num_or_sections`` is an int, then ``num_or_sections``
  2055. indicates the number of equal sized sub-Tensors that the ``x`` will be divided into.
  2056. If ``num_or_sections`` is a list or tuple, the length of it indicates the number of
  2057. sub-Tensors and the elements in it indicate the sizes of sub-Tensors' dimension orderly.
  2058. The length of the list must not be larger than the ``x`` 's size of specified ``axis``.
  2059. axis (int|Tensor, optional): The axis along which to split, it can be a integer or a ``0-D Tensor``
  2060. with shape [] and data type ``int32`` or ``int64``.
  2061. If :math::`axis < 0`, the axis to split along is :math:`rank(x) + axis`. Default is 0.
  2062. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  2063. For more information, please refer to :ref:`api_guide_Name` .
  2064. Returns:
  2065. list(Tensor), The list of segmented Tensors.
  2066. Examples:
  2067. .. code-block:: python
  2068. >>> import paddle
  2069. >>> # x is a Tensor of shape [3, 9, 5]
  2070. >>> x = paddle.rand([3, 9, 5])
  2071. >>> out0, out1, out2 = paddle.split(x, num_or_sections=3, axis=1)
  2072. >>> print(out0.shape)
  2073. [3, 3, 5]
  2074. >>> print(out1.shape)
  2075. [3, 3, 5]
  2076. >>> print(out2.shape)
  2077. [3, 3, 5]
  2078. >>> out0, out1, out2 = paddle.split(x, num_or_sections=[2, 3, 4], axis=1)
  2079. >>> print(out0.shape)
  2080. [3, 2, 5]
  2081. >>> print(out1.shape)
  2082. [3, 3, 5]
  2083. >>> print(out2.shape)
  2084. [3, 4, 5]
  2085. >>> out0, out1, out2 = paddle.split(x, num_or_sections=[2, 3, -1], axis=1)
  2086. >>> print(out0.shape)
  2087. [3, 2, 5]
  2088. >>> print(out1.shape)
  2089. [3, 3, 5]
  2090. >>> print(out2.shape)
  2091. [3, 4, 5]
  2092. >>> # axis is negative, the real axis is (rank(x) + axis)=1
  2093. >>> out0, out1, out2 = paddle.split(x, num_or_sections=3, axis=-2)
  2094. >>> print(out0.shape)
  2095. [3, 3, 5]
  2096. >>> print(out1.shape)
  2097. [3, 3, 5]
  2098. >>> print(out2.shape)
  2099. [3, 3, 5]
  2100. """
  2101. input = x
  2102. dim = axis
  2103. if in_dynamic_mode():
  2104. if isinstance(dim, Variable):
  2105. dim = dim.item(0)
  2106. assert dim + len(input.shape) >= 0, "(rank(x) + axis) must >= 0"
  2107. dim = (dim + len(input.shape)) if dim < 0 else dim
  2108. if isinstance(num_or_sections, (list, tuple)):
  2109. if paddle.utils._contain_var(num_or_sections):
  2110. for index, item in enumerate(num_or_sections):
  2111. if isinstance(item, Variable):
  2112. num_or_sections[index] = num_or_sections[index].item()
  2113. elif not isinstance(num_or_sections, int):
  2114. raise TypeError(
  2115. "The type of 'num_or_sections' in split must be int, list or tuple in imperative mode, but "
  2116. "received %s." % (type(num_or_sections))
  2117. )
  2118. if isinstance(num_or_sections, int):
  2119. return _C_ops.split_with_num(input, num_or_sections, dim)
  2120. else:
  2121. return _C_ops.split(input, num_or_sections, dim)
  2122. elif in_pir_mode():
  2123. if isinstance(dim, paddle.pir.Value):
  2124. dim.stop_gradient = True
  2125. if isinstance(dim, int):
  2126. assert len(input.shape) + dim >= 0, "(rank(x) + axis) must >= 0"
  2127. dim = (len(input.shape) + dim) if dim < 0 else dim
  2128. input_shape = input.shape
  2129. if not isinstance(num_or_sections, (int, list, tuple)):
  2130. raise TypeError(
  2131. "The type of 'num_or_sections' in split must be int, list or tuple in imperative mode, but "
  2132. "received %s." % (type(num_or_sections))
  2133. )
  2134. if isinstance(num_or_sections, int):
  2135. assert num_or_sections > 0, 'num_or_sections must be than 0.'
  2136. if isinstance(dim, int) and input_shape[dim] > 0:
  2137. assert input_shape[dim] % num_or_sections == 0, (
  2138. "The input's size along the split dimension "
  2139. "must be evenly divisible by Attr(num_or_sections). "
  2140. "But %d is not evenly divisible by %d. "
  2141. % (num_or_sections, input_shape[dim])
  2142. )
  2143. return _C_ops.split_with_num(input, num_or_sections, dim)
  2144. else:
  2145. if isinstance(dim, int) and input_shape[dim] > 0:
  2146. assert (
  2147. len(num_or_sections) <= input_shape[dim]
  2148. ), 'len(num_or_sections) must not be more than input.shape[dim].'
  2149. if paddle.utils._contain_var(num_or_sections):
  2150. num_or_sections = paddle.utils.get_int_tensor_list(
  2151. num_or_sections
  2152. )
  2153. return _C_ops.split(input, num_or_sections, dim)
  2154. else:
  2155. check_variable_and_dtype(
  2156. input,
  2157. 'input',
  2158. [
  2159. 'bool',
  2160. 'bfloat16',
  2161. 'float16',
  2162. 'uint16',
  2163. 'float32',
  2164. 'float64',
  2165. 'int32',
  2166. 'int64',
  2167. 'uint8',
  2168. 'int8',
  2169. ],
  2170. 'split',
  2171. )
  2172. check_type(
  2173. num_or_sections, 'num_or_sections', (list, int, tuple), 'split'
  2174. )
  2175. check_type(dim, 'dim', (int, Variable), 'split')
  2176. if isinstance(dim, Variable):
  2177. check_dtype(dim.dtype, 'dim', ['int32', 'int64'], 'split')
  2178. helper = LayerHelper('split', **locals())
  2179. input_shape = input.shape
  2180. inputs = {'X': input}
  2181. attrs = {
  2182. 'num': num_or_sections if isinstance(num_or_sections, int) else 0
  2183. }
  2184. def _get_SectionsTensorList(one_list):
  2185. tensor_list = []
  2186. unk_dim_idx = -1
  2187. for idx, dim_size in enumerate(one_list):
  2188. if isinstance(dim_size, Variable):
  2189. dim_size.stop_gradient = True
  2190. tensor_list.append(dim_size)
  2191. else:
  2192. assert isinstance(dim_size, int)
  2193. if dim_size == -1:
  2194. assert unk_dim_idx == -1, (
  2195. "Only one value of 'num_or_section' in split can "
  2196. "be -1. But received num_or_section[%d] is also -1."
  2197. % idx
  2198. )
  2199. unk_dim_idx = idx
  2200. temp_out = helper.create_variable_for_type_inference(
  2201. 'int32'
  2202. )
  2203. fill_constant(
  2204. [1], 'int32', dim_size, force_cpu=True, out=temp_out
  2205. )
  2206. tensor_list.append(temp_out)
  2207. return tensor_list
  2208. if isinstance(dim, Variable):
  2209. dim.stop_gradient = True
  2210. inputs['AxisTensor'] = dim
  2211. else:
  2212. assert len(input.shape) + dim >= 0, "(rank(x) + axis) must >= 0"
  2213. dim = (len(input_shape) + dim) if dim < 0 else dim
  2214. attrs['axis'] = dim
  2215. if isinstance(num_or_sections, int):
  2216. assert num_or_sections > 0, 'num_or_sections must be than 0.'
  2217. if isinstance(dim, int) and input_shape[dim] > 0:
  2218. assert input_shape[dim] % num_or_sections == 0, (
  2219. "The input's size along the split dimension "
  2220. "must be evenly divisible by Attr(num_or_sections). "
  2221. "But %d is not evenly divisible by %d. "
  2222. % (num_or_sections, input_shape[dim])
  2223. )
  2224. num = num_or_sections
  2225. else:
  2226. if isinstance(dim, int) and input_shape[dim] > 0:
  2227. assert (
  2228. len(num_or_sections) <= input_shape[dim]
  2229. ), 'len(num_or_sections) must not be more than input.shape[dim].'
  2230. num = len(num_or_sections)
  2231. attrs['sections'] = [
  2232. -1 if isinstance(ele, Variable) else ele
  2233. for ele in num_or_sections
  2234. ]
  2235. if paddle.utils._contain_var(num_or_sections):
  2236. inputs['SectionsTensorList'] = _get_SectionsTensorList(
  2237. num_or_sections
  2238. )
  2239. outs = [
  2240. helper.create_variable_for_type_inference(
  2241. dtype=helper.input_dtype()
  2242. )
  2243. for i in range(num)
  2244. ]
  2245. helper.append_op(
  2246. type='split', inputs=inputs, outputs={'Out': outs}, attrs=attrs
  2247. )
  2248. return outs
  2249. def tensor_split(x, num_or_indices, axis=0, name=None):
  2250. """
  2251. Split the input tensor into multiple sub-Tensors along ``axis``, allowing not being of equal size.
  2252. Args:
  2253. x (Tensor): A Tensor whose dimension must be greater than 0. The data type is bool, bfloat16, float16, float32, float64, uint8, int32 or int64.
  2254. num_or_indices (int|list|tuple): If ``num_or_indices`` is an int ``n``, ``x`` is split into ``n`` sections along ``axis``.
  2255. If ``x`` is divisible by ``n``, each section will be ``x.shape[axis] / n``. If ``x`` is not divisible by ``n``, the first
  2256. ``int(x.shape[axis] % n)`` sections will have size ``int(x.shape[axis] / n) + 1``, and the rest will be ``int(x.shape[axis] / n).
  2257. If ``num_or_indices`` is a list or tuple of integer indices, ``x`` is split along ``axis`` at each of the indices. For instance,
  2258. ``num_or_indices=[2, 4]`` with ``axis=0`` would split ``x`` into ``x[:2]``, ``x[2:4]`` and ``x[4:]`` along axis 0.
  2259. axis (int|Tensor, optional): The axis along which to split, it can be a integer or a ``0-D Tensor``
  2260. with shape [] and data type ``int32`` or ``int64``.
  2261. If :math::`axis < 0`, the axis to split along is :math:`rank(x) + axis`. Default is 0.
  2262. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  2263. For more information, please refer to :ref:`api_guide_Name` .
  2264. Returns:
  2265. list[Tensor], The list of segmented Tensors.
  2266. Examples:
  2267. .. code-block:: python
  2268. >>> import paddle
  2269. >>> # x is a Tensor of shape [8]
  2270. >>> # evenly split
  2271. >>> x = paddle.rand([8])
  2272. >>> out0, out1 = paddle.tensor_split(x, num_or_indices=2)
  2273. >>> print(out0.shape)
  2274. [4]
  2275. >>> print(out1.shape)
  2276. [4]
  2277. >>> # not evenly split
  2278. >>> out0, out1, out2 = paddle.tensor_split(x, num_or_indices=3)
  2279. >>> print(out0.shape)
  2280. [3]
  2281. >>> print(out1.shape)
  2282. [3]
  2283. >>> print(out2.shape)
  2284. [2]
  2285. >>> # split with indices
  2286. >>> out0, out1, out2 = paddle.tensor_split(x, num_or_indices=[2, 3])
  2287. >>> print(out0.shape)
  2288. [2]
  2289. >>> print(out1.shape)
  2290. [1]
  2291. >>> print(out2.shape)
  2292. [5]
  2293. >>> # split along axis
  2294. >>> # x is a Tensor of shape [7, 8]
  2295. >>> x = paddle.rand([7, 8])
  2296. >>> out0, out1 = paddle.tensor_split(x, num_or_indices=2, axis=1)
  2297. >>> print(out0.shape)
  2298. [7, 4]
  2299. >>> print(out1.shape)
  2300. [7, 4]
  2301. >>> out0, out1, out2 = paddle.tensor_split(x, num_or_indices=[2, 3], axis=1)
  2302. >>> print(out0.shape)
  2303. [7, 2]
  2304. >>> print(out1.shape)
  2305. [7, 1]
  2306. >>> print(out2.shape)
  2307. [7, 5]
  2308. """
  2309. if x.ndim <= 0 or x.ndim <= axis:
  2310. raise ValueError(
  2311. f"The input tensor's dimension must be greater than 0 or axis which is {axis}, but got {x.ndim}"
  2312. )
  2313. total_n = x.shape[axis]
  2314. def _tensor_split_indices(x, total_n, indices, axis):
  2315. splits = []
  2316. starts = 0
  2317. ends = 0
  2318. for idx in list(indices) + [total_n]:
  2319. ends = idx
  2320. # convert index < 0 to positive
  2321. starts_index = starts if starts >= 0 else total_n + starts
  2322. ends_index = ends if ends >= 0 else total_n + ends
  2323. # ends index should equal or larger than starts
  2324. ends_index = max(starts_index, ends_index)
  2325. sub_array = paddle.slice(
  2326. x, axes=[axis], starts=[starts_index], ends=[ends_index]
  2327. )
  2328. splits.append(sub_array)
  2329. starts = ends
  2330. return splits
  2331. def _tensor_split_sections(x, total_n, sections, axis):
  2332. if sections <= 0:
  2333. raise ValueError('num_or_indices must be larger than 0.')
  2334. base, mod = divmod(total_n, sections)
  2335. num_or_sections = [base + 1] * mod + [base] * (sections - mod)
  2336. return split(x, num_or_sections, axis)
  2337. if isinstance(num_or_indices, int):
  2338. return _tensor_split_sections(x, total_n, num_or_indices, axis)
  2339. elif isinstance(num_or_indices, (list, tuple)):
  2340. return _tensor_split_indices(x, total_n, num_or_indices, axis)
  2341. else:
  2342. raise ValueError(
  2343. f"The num_or_indices should be int, list or tuple of ints, but got {type(num_or_indices)}"
  2344. )
  2345. def hsplit(x, num_or_indices, name=None):
  2346. """
  2347. Split the input tensor into multiple sub-Tensors along the horizontal axis, which is equivalent to ``paddle.tensor_split`` with ``axis=1``
  2348. when ``x`` 's dimension is larger than 1, or equivalent to ``paddle.tensor_split`` with ``axis=0`` when ``x`` 's dimension is 1.
  2349. Args:
  2350. x (Tensor): A Tensor whose dimension must be greater than 0. The data type is bool, bfloat16, float16, float32, float64, uint8, int32 or int64.
  2351. num_or_indices (int|list|tuple): If ``num_or_indices`` is an int ``n``, ``x`` is split into ``n`` sections.
  2352. If ``num_or_indices`` is a list or tuple of integer indices, ``x`` is split at each of the indices.
  2353. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  2354. For more information, please refer to :ref:`api_guide_Name` .
  2355. Returns:
  2356. list[Tensor], The list of segmented Tensors.
  2357. Examples:
  2358. .. code-block:: python
  2359. >>> import paddle
  2360. >>> # x is a Tensor of shape [8]
  2361. >>> x = paddle.rand([8])
  2362. >>> out0, out1 = paddle.hsplit(x, num_or_indices=2)
  2363. >>> print(out0.shape)
  2364. [4]
  2365. >>> print(out1.shape)
  2366. [4]
  2367. >>> # x is a Tensor of shape [7, 8]
  2368. >>> x = paddle.rand([7, 8])
  2369. >>> out0, out1 = paddle.hsplit(x, num_or_indices=2)
  2370. >>> print(out0.shape)
  2371. [7, 4]
  2372. >>> print(out1.shape)
  2373. [7, 4]
  2374. >>> out0, out1, out2 = paddle.hsplit(x, num_or_indices=[1, 4])
  2375. >>> print(out0.shape)
  2376. [7, 1]
  2377. >>> print(out1.shape)
  2378. [7, 3]
  2379. >>> print(out2.shape)
  2380. [7, 4]
  2381. """
  2382. if x.ndim < 1:
  2383. raise ValueError(
  2384. f"The input tensor's dimension must be greater than 0, but got {x.ndim}"
  2385. )
  2386. if x.ndim > 1:
  2387. return tensor_split(x, num_or_indices, axis=1, name=name)
  2388. else:
  2389. return tensor_split(x, num_or_indices, axis=0, name=name)
  2390. def dsplit(x, num_or_indices, name=None):
  2391. """
  2392. Split the input tensor into multiple sub-Tensors along the depth axis, which is equivalent to ``paddle.tensor_split`` with ``axis=2``.
  2393. Args:
  2394. x (Tensor): A Tensor whose dimension must be greater than 2. The data type is bool, bfloat16, float16, float32, float64, uint8, int32 or int64.
  2395. num_or_indices (int|list|tuple): If ``num_or_indices`` is an int ``n``, ``x`` is split into ``n`` sections.
  2396. If ``num_or_indices`` is a list or tuple of integer indices, ``x`` is split at each of the indices.
  2397. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  2398. For more information, please refer to :ref:`api_guide_Name` .
  2399. Returns:
  2400. list[Tensor], The list of segmented Tensors.
  2401. Examples:
  2402. .. code-block:: python
  2403. >>> import paddle
  2404. >>> # x is a Tensor of shape [7, 6, 8]
  2405. >>> x = paddle.rand([7, 6, 8])
  2406. >>> out0, out1 = paddle.dsplit(x, num_or_indices=2)
  2407. >>> print(out0.shape)
  2408. [7, 6, 4]
  2409. >>> print(out1.shape)
  2410. [7, 6, 4]
  2411. >>> out0, out1, out2 = paddle.dsplit(x, num_or_indices=[1, 4])
  2412. >>> print(out0.shape)
  2413. [7, 6, 1]
  2414. >>> print(out1.shape)
  2415. [7, 6, 3]
  2416. >>> print(out2.shape)
  2417. [7, 6, 4]
  2418. """
  2419. if x.ndim < 3:
  2420. raise ValueError(
  2421. f"The input tensor's dimension must be greater than 2, but got {x.ndim}"
  2422. )
  2423. return tensor_split(x, num_or_indices, axis=2, name=name)
  2424. def vsplit(x, num_or_indices, name=None):
  2425. """
  2426. Split the input tensor into multiple sub-Tensors along the vertical axis, which is equivalent to ``paddle.tensor_split`` with ``axis=0``.
  2427. Args:
  2428. x (Tensor): A Tensor whose dimension must be greater than 1. The data type is bool, bfloat16, float16, float32, float64, uint8, int32 or int64.
  2429. num_or_indices (int|list|tuple): If ``num_or_indices`` is an int ``n``, ``x`` is split into ``n`` sections.
  2430. If ``num_or_indices`` is a list or tuple of integer indices, ``x`` is split at each of the indices.
  2431. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  2432. For more information, please refer to :ref:`api_guide_Name` .
  2433. Returns:
  2434. list[Tensor], The list of segmented Tensors.
  2435. Examples:
  2436. .. code-block:: python
  2437. >>> import paddle
  2438. >>> # x is a Tensor of shape [8, 6, 7]
  2439. >>> x = paddle.rand([8, 6, 7])
  2440. >>> out0, out1 = paddle.vsplit(x, num_or_indices=2)
  2441. >>> print(out0.shape)
  2442. [4, 6, 7]
  2443. >>> print(out1.shape)
  2444. [4, 6, 7]
  2445. >>> out0, out1, out2 = paddle.vsplit(x, num_or_indices=[1, 4])
  2446. >>> print(out0.shape)
  2447. [1, 6, 7]
  2448. >>> print(out1.shape)
  2449. [3, 6, 7]
  2450. >>> print(out2.shape)
  2451. [4, 6, 7]
  2452. """
  2453. if x.ndim < 2:
  2454. raise ValueError(
  2455. f"The input tensor's dimension must be greater than 1, but got {x.ndim}"
  2456. )
  2457. return tensor_split(x, num_or_indices, axis=0, name=name)
  2458. def squeeze(x, axis=None, name=None):
  2459. """
  2460. Squeeze the dimension(s) of size 1 of input tensor x's shape.
  2461. Note that the output Tensor will share data with origin Tensor and doesn't have a
  2462. Tensor copy in ``dygraph`` mode. If you want to use the Tensor copy version,
  2463. please use `Tensor.clone` like ``squeeze_clone_x = x.squeeze().clone()``.
  2464. If axis is provided, it will remove the dimension(s) by given axis that of size 1.
  2465. If the dimension of given axis is not of size 1, the dimension remain unchanged.
  2466. If axis is not provided, all dims equal of size 1 will be removed.
  2467. .. code-block:: text
  2468. Case1:
  2469. Input:
  2470. x.shape = [1, 3, 1, 5] # If axis is not provided, all dims equal of size 1 will be removed.
  2471. axis = None
  2472. Output:
  2473. out.shape = [3, 5]
  2474. Case2:
  2475. Input:
  2476. x.shape = [1, 3, 1, 5] # If axis is provided, it will remove the dimension(s) by given axis that of size 1.
  2477. axis = 0
  2478. Output:
  2479. out.shape = [3, 1, 5]
  2480. Case4:
  2481. Input:
  2482. x.shape = [1, 3, 1, 5] # If the dimension of one given axis (3) is not of size 1, the dimension remain unchanged.
  2483. axis = [0, 2, 3]
  2484. Output:
  2485. out.shape = [3, 5]
  2486. Case4:
  2487. Input:
  2488. x.shape = [1, 3, 1, 5] # If axis is negative, axis = axis + ndim (number of dimensions in x).
  2489. axis = [-2]
  2490. Output:
  2491. out.shape = [1, 3, 5]
  2492. Args:
  2493. x (Tensor): The input Tensor. Supported data type: float32, float64, bool, int8, int32, int64.
  2494. axis (int|list|tuple, optional): An integer or list/tuple of integers, indicating the dimensions to be squeezed. Default is None.
  2495. The range of axis is :math:`[-ndim(x), ndim(x))`.
  2496. If axis is negative, :math:`axis = axis + ndim(x)`.
  2497. If axis is None, all the dimensions of x of size 1 will be removed.
  2498. name (str, optional): Please refer to :ref:`api_guide_Name`, Default None.
  2499. Returns:
  2500. Tensor, Squeezed Tensor with the same data type as input Tensor.
  2501. Examples:
  2502. .. code-block:: python
  2503. >>> import paddle
  2504. >>> x = paddle.rand([5, 1, 10])
  2505. >>> output = paddle.squeeze(x, axis=1)
  2506. >>> print(x.shape)
  2507. [5, 1, 10]
  2508. >>> print(output.shape)
  2509. [5, 10]
  2510. >>> # output shares data with x in dygraph mode
  2511. >>> x[0, 0, 0] = 10.
  2512. >>> print(output[0, 0])
  2513. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  2514. 10.)
  2515. """
  2516. if axis is None:
  2517. axis = []
  2518. elif isinstance(axis, int):
  2519. axis = [axis]
  2520. elif isinstance(axis, tuple):
  2521. axis = list(axis)
  2522. input = x
  2523. axes = axis
  2524. if in_dynamic_mode():
  2525. return _C_ops.squeeze(input, axes)
  2526. elif in_pir_mode():
  2527. if isinstance(axes, int):
  2528. axes = [axes]
  2529. if isinstance(axes, paddle.pir.Value):
  2530. axes.stop_gradient = True
  2531. elif isinstance(axes, (list, tuple)):
  2532. if paddle.utils._contain_var(axes):
  2533. axes = paddle.utils.get_int_tensor_list(
  2534. axes, default_dtype='int64'
  2535. )
  2536. return _C_ops.squeeze(input, axes)
  2537. else:
  2538. helper = LayerHelper("squeeze", **locals())
  2539. check_variable_and_dtype(
  2540. input,
  2541. 'input',
  2542. [
  2543. 'float16',
  2544. 'uint16',
  2545. 'float32',
  2546. 'float64',
  2547. 'bool',
  2548. 'int8',
  2549. 'int32',
  2550. 'int64',
  2551. 'complex64',
  2552. 'complex128',
  2553. ],
  2554. 'squeeze',
  2555. )
  2556. check_type(axes, 'axis/axes', (int, list, tuple, Variable), 'squeeze')
  2557. attrs = {}
  2558. if isinstance(axes, Variable):
  2559. axes.stop_gradient = True
  2560. attrs["axes"] = axes
  2561. elif isinstance(axes, (list, tuple)):
  2562. if paddle.utils._contain_var(axes):
  2563. attrs["axes"] = paddle.utils._convert_to_tensor_list(axes)
  2564. else:
  2565. attrs["axes"] = axes
  2566. out = helper.create_variable_for_type_inference(dtype=input.dtype)
  2567. x_shape = helper.create_variable_for_type_inference(dtype=input.dtype)
  2568. helper.append_op(
  2569. type="squeeze2",
  2570. inputs={"X": input},
  2571. attrs=attrs,
  2572. outputs={"Out": out, "XShape": x_shape},
  2573. )
  2574. return out
  2575. @inplace_apis_in_dygraph_only
  2576. def squeeze_(x, axis=None, name=None):
  2577. """
  2578. Inplace version of ``squeeze`` API, the output Tensor will be inplaced with input ``x``.
  2579. Please refer to :ref:`api_paddle_tensor_squeeze`.
  2580. """
  2581. if axis is None:
  2582. axis = []
  2583. elif isinstance(axis, int):
  2584. axis = [axis]
  2585. elif isinstance(axis, tuple):
  2586. axis = list(axis)
  2587. input = x
  2588. axes = axis
  2589. if in_dynamic_mode():
  2590. return _C_ops.squeeze_(input, axes)
  2591. def unique_consecutive(
  2592. x,
  2593. return_inverse=False,
  2594. return_counts=False,
  2595. axis=None,
  2596. dtype="int64",
  2597. name=None,
  2598. ):
  2599. """
  2600. Eliminates all but the first element from every consecutive group of equivalent elements.
  2601. Note:
  2602. This function is different from :ref:`api_paddle_unique` in the sense that this function
  2603. only eliminates consecutive duplicate values. This semantics is similar to :ref:`api_paddle_unique` in C++.
  2604. Args:
  2605. x(Tensor): the input tensor, it's data type should be float32, float64, int32, int64.
  2606. return_inverse(bool, optional): If True, also return the indices for where elements in
  2607. the original input ended up in the returned unique consecutive tensor. Default is False.
  2608. return_counts(bool, optional): If True, also return the counts for each unique consecutive element.
  2609. Default is False.
  2610. axis(int, optional): The axis to apply unique consecutive. If None, the input will be flattened.
  2611. Default is None.
  2612. dtype(np.dtype|str, optional): The data type `inverse` tensor: int32 or int64.
  2613. Default: int64.
  2614. name(str, optional): Name for the operation. For more information, please refer to
  2615. :ref:`api_guide_Name`. Default is None.
  2616. Returns:
  2617. - out (Tensor), the unique consecutive tensor for x.
  2618. - inverse (Tensor), the element of the input tensor corresponds to
  2619. the index of the elements in the unique consecutive tensor for x.
  2620. inverse is provided only if return_inverse is True.
  2621. - counts (Tensor), the counts of the every unique consecutive element in the input tensor.
  2622. counts is provided only if return_counts is True.
  2623. Examples:
  2624. .. code-block:: python
  2625. >>> import paddle
  2626. >>> x = paddle.to_tensor([1, 1, 2, 2, 3, 1, 1, 2])
  2627. >>> output = paddle.unique_consecutive(x) #
  2628. >>> print(output)
  2629. Tensor(shape=[5], dtype=int64, place=Place(cpu), stop_gradient=True,
  2630. [1, 2, 3, 1, 2])
  2631. >>> _, inverse, counts = paddle.unique_consecutive(x, return_inverse=True, return_counts=True)
  2632. >>> print(inverse)
  2633. Tensor(shape=[8], dtype=int64, place=Place(cpu), stop_gradient=True,
  2634. [0, 0, 1, 1, 2, 3, 3, 4])
  2635. >>> print(counts)
  2636. Tensor(shape=[5], dtype=int64, place=Place(cpu), stop_gradient=True,
  2637. [2, 2, 1, 2, 1])
  2638. >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3], [2, 1, 3]])
  2639. >>> output = paddle.unique_consecutive(x, axis=0) #
  2640. >>> print(output)
  2641. Tensor(shape=[3, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  2642. [[2, 1, 3],
  2643. [3, 0, 1],
  2644. [2, 1, 3]])
  2645. >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3], [2, 1, 3]])
  2646. >>> output = paddle.unique_consecutive(x, axis=0) #
  2647. >>> print(output)
  2648. Tensor(shape=[3, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  2649. [[2, 1, 3],
  2650. [3, 0, 1],
  2651. [2, 1, 3]])
  2652. """
  2653. if axis is None:
  2654. axis = []
  2655. else:
  2656. axis = [axis]
  2657. attr_dtype = dtype
  2658. if not isinstance(
  2659. attr_dtype, (core.VarDesc.VarType, paddle.pir.core.DataType)
  2660. ):
  2661. attr_dtype = convert_np_dtype_to_dtype_(dtype)
  2662. if in_dynamic_or_pir_mode():
  2663. out, inverse, counts = _C_ops.unique_consecutive(
  2664. x, return_inverse, return_counts, axis, attr_dtype
  2665. )
  2666. outs = [out]
  2667. if return_inverse:
  2668. outs.append(inverse)
  2669. if return_counts:
  2670. outs.append(counts)
  2671. if len(outs) == 1:
  2672. return outs[0]
  2673. return tuple(outs)
  2674. else:
  2675. check_variable_and_dtype(
  2676. x,
  2677. "input",
  2678. ['float32', 'float64', 'int32', 'int64'],
  2679. 'unique_consecutive',
  2680. )
  2681. check_type(return_inverse, 'return_inverse', bool, 'unique_consecutive')
  2682. check_type(return_counts, 'return_counts', bool, 'unique_consecutive')
  2683. check_dtype(dtype, 'dtype', ['int32', 'int64'], 'unique_consecutive')
  2684. if len(axis) != 0:
  2685. check_type(axis[0], 'axis', int, 'unique_consecutive')
  2686. helper = LayerHelper('unique_consecutive', **locals())
  2687. attrs = {
  2688. 'dtype': attr_dtype,
  2689. "return_inverse": return_inverse,
  2690. "return_counts": return_counts,
  2691. "axis": axis,
  2692. }
  2693. out = helper.create_variable_for_type_inference(
  2694. dtype=x.dtype, stop_gradient=True
  2695. )
  2696. inverse = helper.create_variable_for_type_inference(
  2697. dtype=attr_dtype, stop_gradient=True
  2698. )
  2699. counts = helper.create_variable_for_type_inference(
  2700. dtype=attr_dtype, stop_gradient=True
  2701. )
  2702. outputs = {"Out": out, "Index": inverse, "Counts": counts}
  2703. outs = [out]
  2704. if return_inverse:
  2705. outs.append(inverse)
  2706. if return_counts:
  2707. outs.append(counts)
  2708. helper.append_op(
  2709. type="unique_consecutive",
  2710. inputs={"X": x},
  2711. attrs=attrs,
  2712. outputs=outputs,
  2713. )
  2714. if len(outs) == 1:
  2715. return outs[0]
  2716. return tuple(outs)
  2717. def unique(
  2718. x,
  2719. return_index=False,
  2720. return_inverse=False,
  2721. return_counts=False,
  2722. axis=None,
  2723. dtype="int64",
  2724. name=None,
  2725. ):
  2726. r"""
  2727. Returns the unique elements of `x` in ascending order.
  2728. Args:
  2729. x(Tensor): The input tensor, it's data type should be float32, float64, int32, int64.
  2730. return_index(bool, optional): If True, also return the indices of the input tensor that
  2731. result in the unique Tensor.
  2732. return_inverse(bool, optional): If True, also return the indices for where elements in
  2733. the original input ended up in the returned unique tensor.
  2734. return_counts(bool, optional): If True, also return the counts for each unique element.
  2735. axis(int, optional): The axis to apply unique. If None, the input will be flattened.
  2736. Default: None.
  2737. dtype(np.dtype|str, optional): The date type of `indices` or `inverse` tensor: int32 or int64.
  2738. Default: int64.
  2739. name(str, optional): Name for the operation. For more information, please refer to
  2740. :ref:`api_guide_Name`. Default: None.
  2741. Returns:
  2742. tuple (out, indices, inverse, counts). `out` is the unique tensor for `x`. `indices` is \
  2743. provided only if `return_index` is True. `inverse` is provided only if `return_inverse` \
  2744. is True. `counts` is provided only if `return_counts` is True.
  2745. Examples:
  2746. .. code-block:: python
  2747. >>> import paddle
  2748. >>> x = paddle.to_tensor([2, 3, 3, 1, 5, 3])
  2749. >>> unique = paddle.unique(x)
  2750. >>> print(unique)
  2751. Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
  2752. [1, 2, 3, 5])
  2753. >>> _, indices, inverse, counts = paddle.unique(x, return_index=True, return_inverse=True, return_counts=True)
  2754. >>> print(indices)
  2755. Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
  2756. [3, 0, 1, 4])
  2757. >>> print(inverse)
  2758. Tensor(shape=[6], dtype=int64, place=Place(cpu), stop_gradient=True,
  2759. [1, 2, 2, 0, 3, 2])
  2760. >>> print(counts)
  2761. Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
  2762. [1, 1, 3, 1])
  2763. >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3]])
  2764. >>> unique = paddle.unique(x)
  2765. >>> print(unique)
  2766. Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
  2767. [0, 1, 2, 3])
  2768. >>> unique = paddle.unique(x, axis=0)
  2769. >>> print(unique)
  2770. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  2771. [[2, 1, 3],
  2772. [3, 0, 1]])
  2773. """
  2774. if axis is None:
  2775. axis = []
  2776. else:
  2777. axis = [axis]
  2778. attr_dtype = convert_np_dtype_to_dtype_(dtype)
  2779. if in_dynamic_mode():
  2780. out, indices, inverse, counts = _C_ops.unique(
  2781. x, return_index, return_inverse, return_counts, axis, attr_dtype
  2782. )
  2783. outs = [out]
  2784. if return_index:
  2785. outs.append(indices)
  2786. if return_inverse:
  2787. outs.append(inverse)
  2788. if return_counts:
  2789. outs.append(counts)
  2790. if len(outs) == 1:
  2791. return outs[0]
  2792. return tuple(outs)
  2793. elif in_pir_mode():
  2794. out, indices, inverse, counts = _C_ops.unique(
  2795. x,
  2796. return_index,
  2797. return_inverse,
  2798. return_counts,
  2799. axis,
  2800. attr_dtype,
  2801. True,
  2802. )
  2803. outs = [out]
  2804. if return_index:
  2805. outs.append(indices)
  2806. if return_inverse:
  2807. outs.append(inverse)
  2808. if return_counts:
  2809. outs.append(counts)
  2810. if len(outs) == 1:
  2811. return outs[0]
  2812. return tuple(outs)
  2813. else:
  2814. check_variable_and_dtype(
  2815. x,
  2816. "input",
  2817. ['float16', 'uint16', 'float32', 'float64', 'int32', 'int64'],
  2818. 'unique',
  2819. )
  2820. check_type(return_index, 'return_index', bool, 'unique')
  2821. check_type(return_inverse, 'return_inverse', bool, 'unique')
  2822. check_type(return_counts, 'return_counts', bool, 'unique')
  2823. check_dtype(dtype, 'dtype', ['int32', 'int64'], 'unique')
  2824. if len(axis) != 0:
  2825. check_type(axis[0], 'axis', int, 'unique')
  2826. helper = LayerHelper('unique', **locals())
  2827. attrs = {
  2828. 'dtype': attr_dtype,
  2829. "return_index": return_index,
  2830. "return_inverse": return_inverse,
  2831. "return_counts": return_counts,
  2832. "axis": axis,
  2833. "is_sorted": True,
  2834. }
  2835. out = helper.create_variable_for_type_inference(
  2836. dtype=x.dtype, stop_gradient=True
  2837. )
  2838. indices = helper.create_variable_for_type_inference(
  2839. dtype=attr_dtype, stop_gradient=True
  2840. )
  2841. inverse = helper.create_variable_for_type_inference(
  2842. dtype=attr_dtype, stop_gradient=True
  2843. )
  2844. counts = helper.create_variable_for_type_inference(
  2845. dtype=attr_dtype, stop_gradient=True
  2846. )
  2847. outputs = {
  2848. "Out": out,
  2849. "Indices": indices,
  2850. "Index": inverse,
  2851. "Counts": counts,
  2852. }
  2853. outs = [out]
  2854. if return_index:
  2855. outs.append(indices)
  2856. if return_inverse:
  2857. outs.append(inverse)
  2858. if return_counts:
  2859. outs.append(counts)
  2860. helper.append_op(
  2861. type="unique", inputs={"X": x}, attrs=attrs, outputs=outputs
  2862. )
  2863. if len(outs) == 1:
  2864. return outs[0]
  2865. return tuple(outs)
  2866. def unsqueeze(x, axis, name=None):
  2867. """
  2868. Insert single-dimensional entries to the shape of input Tensor ``x``. Takes one
  2869. required argument axis, a dimension or list of dimensions that will be inserted.
  2870. Dimension indices in axis are as seen in the output tensor.
  2871. Note that the output Tensor will share data with origin Tensor and doesn't have a
  2872. Tensor copy in ``dygraph`` mode. If you want to use the Tensor copy version,
  2873. please use `Tensor.clone` like ``unsqueeze_clone_x = x.unsqueeze(-1).clone()``.
  2874. Args:
  2875. x (Tensor): The input Tensor to be unsqueezed. Supported data type: bfloat16, float16, float32, float64, bool, int8, int32, int64.
  2876. axis (int|list|tuple|Tensor): Indicates the dimensions to be inserted. The data type is ``int32`` .
  2877. If ``axis`` is a list or tuple, each element of it should be integer or 0-D Tensor with shape [].
  2878. If ``axis`` is a Tensor, it should be an 1-D Tensor .
  2879. If ``axis`` is negative, ``axis = axis + ndim(x) + 1``.
  2880. name (str|None): Name for this layer. Please refer to :ref:`api_guide_Name`, Default None.
  2881. Returns:
  2882. Tensor, Unsqueezed Tensor with the same data type as input Tensor.
  2883. Examples:
  2884. .. code-block:: python
  2885. >>> import paddle
  2886. >>> x = paddle.rand([5, 10])
  2887. >>> print(x.shape)
  2888. [5, 10]
  2889. >>> out1 = paddle.unsqueeze(x, axis=0)
  2890. >>> print(out1.shape)
  2891. [1, 5, 10]
  2892. >>> out2 = paddle.unsqueeze(x, axis=[0, 2])
  2893. >>> print(out2.shape)
  2894. [1, 5, 1, 10]
  2895. >>> axis = paddle.to_tensor([0, 1, 2])
  2896. >>> out3 = paddle.unsqueeze(x, axis=axis)
  2897. >>> print(out3.shape)
  2898. [1, 1, 1, 5, 10]
  2899. >>> # out1, out2, out3 share data with x in dygraph mode
  2900. >>> x[0, 0] = 10.
  2901. >>> print(out1[0, 0, 0])
  2902. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  2903. 10.)
  2904. >>> print(out2[0, 0, 0, 0])
  2905. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  2906. 10.)
  2907. >>> print(out3[0, 0, 0, 0, 0])
  2908. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  2909. 10.)
  2910. """
  2911. input = x
  2912. axes = axis
  2913. if in_dynamic_mode():
  2914. if isinstance(axes, int):
  2915. axes = [axes]
  2916. elif isinstance(axes, Variable):
  2917. axes = axes.tolist()
  2918. elif isinstance(axes, (list, tuple)):
  2919. axes = [
  2920. item.item(0) if isinstance(item, Variable) else item
  2921. for item in axes
  2922. ]
  2923. return _C_ops.unsqueeze(input, axes)
  2924. elif in_pir_mode():
  2925. if isinstance(axes, int):
  2926. axes = [axes]
  2927. if isinstance(axes, paddle.pir.Value):
  2928. axes.stop_gradient = True
  2929. elif isinstance(axes, (list, tuple)):
  2930. if paddle.utils._contain_var(axes):
  2931. axes = paddle.utils.get_int_tensor_list(
  2932. axes, default_dtype='int64'
  2933. )
  2934. return _C_ops.unsqueeze(input, axes)
  2935. else:
  2936. check_type(axes, 'axis/axes', (int, list, tuple, Variable), 'unsqueeze')
  2937. check_variable_and_dtype(
  2938. input,
  2939. 'input',
  2940. [
  2941. 'uint16',
  2942. 'float16',
  2943. 'uint16',
  2944. 'float32',
  2945. 'float64',
  2946. 'bool',
  2947. 'int8',
  2948. 'int16',
  2949. 'int32',
  2950. 'int64',
  2951. 'complex64',
  2952. 'complex128',
  2953. ],
  2954. 'unsqueeze',
  2955. )
  2956. helper = LayerHelper("unsqueeze2", **locals())
  2957. inputs = {"X": input}
  2958. attrs = {}
  2959. if isinstance(axes, int):
  2960. axes = [axes]
  2961. if isinstance(axes, Variable):
  2962. axes.stop_gradient = True
  2963. inputs["AxesTensor"] = axes
  2964. elif isinstance(axes, (list, tuple)):
  2965. if paddle.utils._contain_var(axes):
  2966. inputs["AxesTensorList"] = paddle.utils._convert_to_tensor_list(
  2967. axes
  2968. )
  2969. else:
  2970. attrs["axes"] = axes
  2971. out = helper.create_variable_for_type_inference(dtype=input.dtype)
  2972. x_shape = helper.create_variable_for_type_inference(dtype=input.dtype)
  2973. helper.append_op(
  2974. type="unsqueeze2",
  2975. inputs=inputs,
  2976. attrs=attrs,
  2977. outputs={"Out": out, "XShape": x_shape},
  2978. )
  2979. return out
  2980. @inplace_apis_in_dygraph_only
  2981. def unsqueeze_(x, axis, name=None):
  2982. """
  2983. Inplace version of ``unsqueeze`` API, the output Tensor will be inplaced with input ``x``.
  2984. Please refer to :ref:`api_paddle_tensor_unsqueeze`.
  2985. """
  2986. input = x
  2987. axes = axis
  2988. if isinstance(axes, int):
  2989. axes = [axes]
  2990. elif isinstance(axes, Variable):
  2991. axes = axes.tolist()
  2992. elif isinstance(axes, (list, tuple)):
  2993. axes = [
  2994. item.item(0) if isinstance(item, Variable) else item
  2995. for item in axes
  2996. ]
  2997. return _C_ops.unsqueeze_(input, axes)
  2998. def gather(x, index, axis=None, name=None):
  2999. """
  3000. Output is obtained by gathering entries of ``axis``
  3001. of ``x`` indexed by ``index`` and concatenate them together.
  3002. .. code-block:: text
  3003. Given:
  3004. x = [[1, 2],
  3005. [3, 4],
  3006. [5, 6]]
  3007. index = [1, 2]
  3008. axis=[0]
  3009. Then:
  3010. out = [[3, 4],
  3011. [5, 6]]
  3012. Args:
  3013. x (Tensor): The source input tensor with rank>=1. Supported data type is
  3014. int32, int64, float32, float64, complex64, complex128 and uint8 (only for CPU),
  3015. float16 (only for GPU).
  3016. index (Tensor): The index input tensor with rank=0 or rank=1. Data type is int32 or int64.
  3017. axis (Tensor|int, optional): The axis of input to be gathered, it's can be int or a Tensor with data type is int32 or int64. The default value is None, if None, the ``axis`` is 0.
  3018. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  3019. For more information, please refer to :ref:`api_guide_Name` .
  3020. Returns:
  3021. output (Tensor), If the index is a 1-D tensor, the output is a tensor with the same shape as ``x``. If the index is a 0-D tensor, the output will reduce the dimension where the axis pointing.
  3022. Examples:
  3023. .. code-block:: python
  3024. >>> import paddle
  3025. >>> input = paddle.to_tensor([[1,2],[3,4],[5,6]])
  3026. >>> index = paddle.to_tensor([0,1])
  3027. >>> output = paddle.gather(input, index, axis=0)
  3028. >>> print(output)
  3029. Tensor(shape=[2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
  3030. [[1, 2],
  3031. [3, 4]])
  3032. """
  3033. if axis is None:
  3034. axis = 0
  3035. if in_dynamic_or_pir_mode():
  3036. return _C_ops.gather(x, index, axis)
  3037. else:
  3038. check_variable_and_dtype(
  3039. x,
  3040. 'x',
  3041. [
  3042. 'float16',
  3043. 'float32',
  3044. 'float64',
  3045. 'int16',
  3046. 'int32',
  3047. 'int64',
  3048. 'uint8',
  3049. 'uint16',
  3050. 'complex64',
  3051. 'complex128',
  3052. ],
  3053. 'gather',
  3054. )
  3055. check_variable_and_dtype(index, 'index', ['int32', 'int64'], 'gather')
  3056. if isinstance(axis, Variable):
  3057. check_variable_and_dtype(axis, 'axis', ['int32', 'int64'], 'gather')
  3058. helper = LayerHelper('gather', **locals())
  3059. dtype = helper.input_dtype('x')
  3060. out = helper.create_variable_for_type_inference(dtype)
  3061. if not isinstance(axis, Variable):
  3062. helper.append_op(
  3063. type="gather",
  3064. inputs={"X": x, "Index": index},
  3065. attrs={'axis': axis, 'overwrite': False},
  3066. outputs={"Out": out},
  3067. )
  3068. else:
  3069. helper.append_op(
  3070. type="gather",
  3071. inputs={"X": x, "Index": index, "Axis": axis},
  3072. attrs={"overwrite": False},
  3073. outputs={"Out": out},
  3074. )
  3075. return out
  3076. def unbind(input, axis=0):
  3077. """
  3078. Removes a tensor dimension, then split the input tensor into multiple sub-Tensors.
  3079. Args:
  3080. input (Tensor): The input variable which is an N-D Tensor, data type being bool, float16, float32, float64, int32, int64, complex64 or complex128.
  3081. axis (int32|int64, optional): A 0-D Tensor with shape [] and type is ``int32|int64``. The dimension along which to unbind.
  3082. If :math:`axis < 0`, the dimension to unbind along is :math:`rank(input) + axis`. Default is 0.
  3083. Returns:
  3084. list(Tensor), The list of segmented Tensor variables.
  3085. Examples:
  3086. .. code-block:: python
  3087. >>> import paddle
  3088. >>> # input is a Tensor which shape is [3, 4, 5]
  3089. >>> input = paddle.rand([3, 4, 5])
  3090. >>> [x0, x1, x2] = paddle.unbind(input, axis=0)
  3091. >>> # x0.shape [4, 5]
  3092. >>> # x1.shape [4, 5]
  3093. >>> # x2.shape [4, 5]
  3094. >>> [x0, x1, x2, x3] = paddle.unbind(input, axis=1)
  3095. >>> # x0.shape [3, 5]
  3096. >>> # x1.shape [3, 5]
  3097. >>> # x2.shape [3, 5]
  3098. >>> # x3.shape [3, 5]
  3099. """
  3100. if not isinstance(axis, (int)):
  3101. raise TypeError(
  3102. "The type of 'axis' must be int, but received %s." % (type(axis))
  3103. )
  3104. if axis not in range(-input.ndim, input.ndim):
  3105. raise ValueError(
  3106. f'The axis must in range({-input.ndim}, {input.ndim}).'
  3107. )
  3108. if in_dynamic_or_pir_mode():
  3109. return _C_ops.unbind(input, axis)
  3110. else:
  3111. if isinstance(axis, np.generic):
  3112. axis = np.asscalar(axis)
  3113. input_shape = input.shape
  3114. axis_ = axis if axis >= 0 else len(input_shape) + axis
  3115. num = input_shape[axis_]
  3116. helper = LayerHelper("unbind", **locals())
  3117. check_type(input, 'input', (Variable), 'unbind')
  3118. dtype = helper.input_dtype()
  3119. check_dtype(
  3120. dtype,
  3121. 'unbind',
  3122. [
  3123. 'bool',
  3124. 'float16',
  3125. 'uint16',
  3126. 'float32',
  3127. 'float64',
  3128. 'int32',
  3129. 'int64',
  3130. 'complex64',
  3131. 'complex128',
  3132. ],
  3133. 'unbind',
  3134. )
  3135. outs = [
  3136. helper.create_variable_for_type_inference(
  3137. dtype=helper.input_dtype()
  3138. )
  3139. for i in range(num)
  3140. ]
  3141. helper.append_op(
  3142. type="unbind",
  3143. inputs={"X": input},
  3144. outputs={"Out": outs},
  3145. attrs={"axis": axis},
  3146. )
  3147. return outs
  3148. def scatter(x, index, updates, overwrite=True, name=None):
  3149. """
  3150. **Scatter Layer**
  3151. Output is obtained by updating the input on selected indices based on updates.
  3152. .. code-block:: python
  3153. :name: scatter-example-1
  3154. >>> import paddle
  3155. >>> #input:
  3156. >>> x = paddle.to_tensor([[1, 1], [2, 2], [3, 3]], dtype='float32')
  3157. >>> index = paddle.to_tensor([2, 1, 0, 1], dtype='int64')
  3158. >>> # shape of updates should be the same as x
  3159. >>> # shape of updates with dim > 1 should be the same as input
  3160. >>> updates = paddle.to_tensor([[1, 1], [2, 2], [3, 3], [4, 4]], dtype='float32')
  3161. >>> overwrite = False
  3162. >>> # calculation:
  3163. >>> if not overwrite:
  3164. ... for i in range(len(index)):
  3165. ... x[index[i]] = paddle.zeros([2])
  3166. >>> for i in range(len(index)):
  3167. ... if (overwrite):
  3168. ... x[index[i]] = updates[i]
  3169. ... else:
  3170. ... x[index[i]] += updates[i]
  3171. >>> # output:
  3172. >>> out = paddle.to_tensor([[3, 3], [6, 6], [1, 1]])
  3173. >>> print(out.shape)
  3174. [3, 2]
  3175. **NOTICE**: The order in which updates are applied is nondeterministic,
  3176. so the output will be nondeterministic if index contains duplicates.
  3177. Args:
  3178. x (Tensor): The input N-D Tensor with ndim>=1. Data type can be float32, float64.
  3179. index (Tensor): The index is a 1-D or 0-D Tensor. Data type can be int32, int64. The length of index cannot exceed updates's length, and the value in index cannot exceed input's length.
  3180. updates (Tensor): Update input with updates parameter based on index. When the index is a 1-D tensor, the updates shape should be the same as input, and dim value with dim > 1 should be the same as input. When the index is a 0-D tensor, the updates should be a (N-1)-D tensor, the ith dim of the updates should be equal with the (i+1)th dim of the input.
  3181. overwrite (bool, optional): The mode that updating the output when there are same indices.If True, use the overwrite mode to update the output of the same index,if False, use the accumulate mode to update the output of the same index. Default value is True.
  3182. name(str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name` .
  3183. Returns:
  3184. Tensor, The output is a Tensor with the same shape as x.
  3185. Examples:
  3186. .. code-block:: python
  3187. :name: scatter-example-2
  3188. >>> import paddle
  3189. >>> x = paddle.to_tensor([[1, 1], [2, 2], [3, 3]], dtype='float32')
  3190. >>> index = paddle.to_tensor([2, 1, 0, 1], dtype='int64')
  3191. >>> updates = paddle.to_tensor([[1, 1], [2, 2], [3, 3], [4, 4]], dtype='float32')
  3192. >>> output1 = paddle.scatter(x, index, updates, overwrite=False)
  3193. >>> print(output1)
  3194. Tensor(shape=[3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  3195. [[3., 3.],
  3196. [6., 6.],
  3197. [1., 1.]])
  3198. >>> output2 = paddle.scatter(x, index, updates, overwrite=True)
  3199. >>> # CPU device:
  3200. >>> # [[3., 3.],
  3201. >>> # [4., 4.],
  3202. >>> # [1., 1.]]
  3203. >>> # GPU device maybe have two results because of the repeated numbers in index
  3204. >>> # result 1:
  3205. >>> # [[3., 3.],
  3206. >>> # [4., 4.],
  3207. >>> # [1., 1.]]
  3208. >>> # result 2:
  3209. >>> # [[3., 3.],
  3210. >>> # [2., 2.],
  3211. >>> # [1., 1.]]
  3212. """
  3213. if in_dynamic_or_pir_mode():
  3214. return _C_ops.scatter(x, index, updates, overwrite)
  3215. else:
  3216. check_variable_and_dtype(
  3217. x,
  3218. 'dtype',
  3219. ['float32', 'float64', 'float16', 'int32', 'int64', 'uint16'],
  3220. 'scatter',
  3221. )
  3222. check_type(overwrite, 'overwrite', bool, 'scatter')
  3223. helper = LayerHelper('scatter', **locals())
  3224. out = helper.create_variable_for_type_inference(x.dtype)
  3225. helper.append_op(
  3226. type="scatter",
  3227. inputs={"X": x, "Ids": index, "Updates": updates},
  3228. attrs={'overwrite': overwrite},
  3229. outputs={"Out": out},
  3230. )
  3231. return out
  3232. @inplace_apis_in_dygraph_only
  3233. def scatter_(x, index, updates, overwrite=True, name=None):
  3234. """
  3235. Inplace version of ``scatter`` API, the output Tensor will be inplaced with input ``x``.
  3236. Please refer to :ref:`api_paddle_tensor_scatter`.
  3237. """
  3238. return _C_ops.scatter_(x, index, updates, overwrite)
  3239. def scatter_nd_add(x, index, updates, name=None):
  3240. r"""
  3241. Output is obtained by applying sparse addition to a single value
  3242. or slice in a Tensor.
  3243. :attr:`x` is a Tensor with ndim :math:`R`
  3244. and :attr:`index` is a Tensor with ndim :math:`K` . Thus, :attr:`index`
  3245. has shape :math:`[i_0, i_1, ..., i_{K-2}, Q]` where :math:`Q \leq R` . :attr:`updates`
  3246. is a Tensor with ndim :math:`K - 1 + R - Q` and its
  3247. shape is :math:`index.shape[:-1] + x.shape[index.shape[-1]:]` .
  3248. According to the :math:`[i_0, i_1, ..., i_{K-2}]` of :attr:`index` ,
  3249. add the corresponding :attr:`updates` slice to the :attr:`x` slice
  3250. which is obtained by the last one dimension of :attr:`index` .
  3251. .. code-block:: text
  3252. Given:
  3253. * Case 1:
  3254. x = [0, 1, 2, 3, 4, 5]
  3255. index = [[1], [2], [3], [1]]
  3256. updates = [9, 10, 11, 12]
  3257. we get:
  3258. output = [0, 22, 12, 14, 4, 5]
  3259. * Case 2:
  3260. x = [[65, 17], [-14, -25]]
  3261. index = [[], []]
  3262. updates = [[[-1, -2], [1, 2]],
  3263. [[3, 4], [-3, -4]]]
  3264. x.shape = (2, 2)
  3265. index.shape = (2, 0)
  3266. updates.shape = (2, 2, 2)
  3267. we get:
  3268. output = [[67, 19], [-16, -27]]
  3269. Args:
  3270. x (Tensor): The x input. Its dtype should be int32, int64, float32, float64.
  3271. index (Tensor): The index input with ndim > 1 and index.shape[-1] <= x.ndim.
  3272. Its dtype should be int32 or int64 as it is used as indexes.
  3273. updates (Tensor): The updated value of scatter_nd_add op, and it must have the same dtype
  3274. as x. It must have the shape index.shape[:-1] + x.shape[index.shape[-1]:].
  3275. name (str|None): The output tensor name. If set None, the layer will be named automatically.
  3276. Returns:
  3277. output (Tensor), The output is a tensor with the same shape and dtype as x.
  3278. Examples:
  3279. .. code-block:: python
  3280. >>> import paddle
  3281. >>> x = paddle.rand(shape=[3, 5, 9, 10], dtype='float32')
  3282. >>> updates = paddle.rand(shape=[3, 9, 10], dtype='float32')
  3283. >>> index = paddle.to_tensor([[1, 1],
  3284. ... [0, 1],
  3285. ... [1, 3]], dtype='int64')
  3286. >>> output = paddle.scatter_nd_add(x, index, updates)
  3287. >>> print(output.shape)
  3288. [3, 5, 9, 10]
  3289. """
  3290. if in_dynamic_or_pir_mode():
  3291. return _C_ops.scatter_nd_add(x, index, updates)
  3292. else:
  3293. if x.dtype != updates.dtype:
  3294. raise ValueError("x and updates must have same data type.")
  3295. helper = LayerHelper('scatter_nd_add', **locals())
  3296. dtype = helper.input_dtype(input_param_name='x')
  3297. output = helper.create_variable_for_type_inference(dtype)
  3298. helper.append_op(
  3299. type="scatter_nd_add",
  3300. inputs={"X": x, "Index": index, "Updates": updates},
  3301. outputs={"Out": output},
  3302. )
  3303. return output
  3304. def scatter_nd(index, updates, shape, name=None):
  3305. """
  3306. **Scatter_nd Layer**
  3307. Output is obtained by scattering the :attr:`updates` in a new tensor according
  3308. to :attr:`index` . This op is similar to :code:`scatter_nd_add`, except the
  3309. tensor of :attr:`shape` is zero-initialized. Correspondingly, :code:`scatter_nd(index, updates, shape)`
  3310. is equal to :code:`scatter_nd_add(paddle.zeros(shape, updates.dtype), index, updates)` .
  3311. If :attr:`index` has repeated elements, then the corresponding updates are accumulated.
  3312. Because of the numerical approximation issues, the different order of repeated elements
  3313. in :attr:`index` may cause different results. The specific calculation method can be
  3314. seen :code:`scatter_nd_add` . This op is the inverse of the :code:`gather_nd` op.
  3315. Args:
  3316. index (Tensor): The index input with ndim >= 1 and index.shape[-1] <= len(shape).
  3317. Its dtype should be int32 or int64 as it is used as indexes.
  3318. updates (Tensor): The updated value of scatter_nd op. Its dtype should be float32, float64.
  3319. It must have the shape index.shape[:-1] + shape[index.shape[-1]:]
  3320. shape(tuple|list): Shape of output tensor.
  3321. name (str|None): The output Tensor name. If set None, the layer will be named automatically.
  3322. Returns:
  3323. output (Tensor), The output is a tensor with the same type as :attr:`updates` .
  3324. Examples:
  3325. .. code-block:: python
  3326. >>> import paddle
  3327. >>> index = paddle.to_tensor([[1, 1],
  3328. ... [0, 1],
  3329. ... [1, 3]], dtype="int64")
  3330. >>> updates = paddle.rand(shape=[3, 9, 10], dtype='float32')
  3331. >>> shape = [3, 5, 9, 10]
  3332. >>> output = paddle.scatter_nd(index, updates, shape)
  3333. """
  3334. return scatter_nd_add(zeros(shape, updates.dtype), index, updates, name)
  3335. def chunk(x, chunks, axis=0, name=None):
  3336. """
  3337. Split the input tensor into multiple sub-Tensors.
  3338. Args:
  3339. x (Tensor): A N-D Tensor. The data type is bool, float16, float32, float64, int32 or int64.
  3340. chunks(int): The number of tensor to be split along the certain axis.
  3341. axis (int|Tensor, optional): The axis along which to split, it can be a integer or a ``0-D Tensor``
  3342. with shape [] and data type ``int32`` or ``int64``.
  3343. If :math::`axis < 0`, the axis to split along is :math:`rank(x) + axis`. Default is 0.
  3344. name (str, optional): The default value is None. Normally there is no need for user to set this property.
  3345. For more information, please refer to :ref:`api_guide_Name` .
  3346. Returns:
  3347. list(Tensor), The list of segmented Tensors.
  3348. Examples:
  3349. .. code-block:: python
  3350. >>> import paddle
  3351. >>> x = paddle.rand([3, 9, 5])
  3352. >>> out0, out1, out2 = paddle.chunk(x, chunks=3, axis=1)
  3353. >>> # out0.shape [3, 3, 5]
  3354. >>> # out1.shape [3, 3, 5]
  3355. >>> # out2.shape [3, 3, 5]
  3356. >>> # axis is negative, the real axis is (rank(x) + axis) which real
  3357. >>> # value is 1.
  3358. >>> out0, out1, out2 = paddle.chunk(x, chunks=3, axis=-2)
  3359. >>> # out0.shape [3, 3, 5]
  3360. >>> # out1.shape [3, 3, 5]
  3361. >>> # out2.shape [3, 3, 5]
  3362. """
  3363. check_type(chunks, 'chunks', (int), 'chunk')
  3364. return split(x, num_or_sections=chunks, axis=axis, name=name)
  3365. def tile(x, repeat_times, name=None):
  3366. """
  3367. Construct a new Tensor by repeating ``x`` the number of times given by ``repeat_times``.
  3368. After tiling, the value of the i'th dimension of the output is equal to ``x.shape[i]*repeat_times[i]``.
  3369. Both the number of dimensions of ``x`` and the number of elements in ``repeat_times`` should be less than or equal to 6.
  3370. Args:
  3371. x (Tensor): The input tensor, its data type should be bool, float16, float32, float64, int32, int64, complex64 or complex128.
  3372. repeat_times (list|tuple|Tensor): The number of repeating times. If repeat_times is a list or tuple, all its elements
  3373. should be integers or 1-D Tensors with the data type int32. If repeat_times is a Tensor, it should be an 1-D Tensor with the data type int32.
  3374. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  3375. Returns:
  3376. N-D Tensor. The data type is the same as ``x``. The size of the i-th dimension is equal to ``x[i] * repeat_times[i]``.
  3377. Examples:
  3378. .. code-block:: python
  3379. >>> import paddle
  3380. >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
  3381. >>> out = paddle.tile(data, repeat_times=[2, 1])
  3382. >>> print(out)
  3383. Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
  3384. [[1, 2, 3],
  3385. [1, 2, 3]])
  3386. >>> out = paddle.tile(data, repeat_times=(2, 2))
  3387. >>> print(out)
  3388. Tensor(shape=[2, 6], dtype=int32, place=Place(cpu), stop_gradient=True,
  3389. [[1, 2, 3, 1, 2, 3],
  3390. [1, 2, 3, 1, 2, 3]])
  3391. >>> repeat_times = paddle.to_tensor([1, 2], dtype='int32')
  3392. >>> out = paddle.tile(data, repeat_times=repeat_times)
  3393. >>> print(out)
  3394. Tensor(shape=[1, 6], dtype=int32, place=Place(cpu), stop_gradient=True,
  3395. [[1, 2, 3, 1, 2, 3]])
  3396. """
  3397. def check_input(x, repeat_times):
  3398. check_type(
  3399. repeat_times,
  3400. 'repeat_times',
  3401. (list, tuple, Variable, paddle.pir.Value),
  3402. 'tile',
  3403. )
  3404. if isinstance(repeat_times, (Variable, paddle.pir.Value)):
  3405. assert (
  3406. len(repeat_times.shape) == 1
  3407. ), 'repeat_times must be a Tensor with ndim == 1.'
  3408. else:
  3409. for elem in repeat_times:
  3410. if isinstance(elem, (Variable, paddle.pir.Value)):
  3411. assert (
  3412. elem.numel() == 1
  3413. ), 'Elements in repeat_times must be Tensor with one element or integers.'
  3414. else:
  3415. type_tuple = (int, np.int32, np.int64)
  3416. assert isinstance(
  3417. elem, type_tuple
  3418. ), 'Elements in repeat_times must be Tensor with one element or integers.'
  3419. check_variable_and_dtype(
  3420. x,
  3421. 'x',
  3422. [
  3423. 'bool',
  3424. 'float16',
  3425. 'uint16',
  3426. 'float32',
  3427. 'float64',
  3428. 'int32',
  3429. 'int64',
  3430. 'complex64',
  3431. 'complex128',
  3432. ],
  3433. 'tile',
  3434. )
  3435. if convert_dtype(x.dtype) == 'bool' and not x.stop_gradient:
  3436. raise ValueError(
  3437. "When the date type is bool for the input 'x' of tile op, you "
  3438. "must set its stop_gradient to be True by "
  3439. "some_var.stop_gradient == True supporting some_var is the input."
  3440. )
  3441. if in_dynamic_mode():
  3442. if isinstance(repeat_times, core.eager.Tensor):
  3443. assert (
  3444. repeat_times.ndim == 1
  3445. ), "Only support ndim == 1 while repeat_times is a Tensor."
  3446. repeat_times = repeat_times.tolist()
  3447. return _C_ops.tile(x, repeat_times)
  3448. elif in_pir_mode():
  3449. check_input(x, repeat_times)
  3450. if isinstance(repeat_times, (list, tuple)):
  3451. if paddle.utils._contain_var(repeat_times):
  3452. repeat_times = paddle.utils.get_int_tensor_list(repeat_times)
  3453. return _C_ops.tile(x, repeat_times)
  3454. else:
  3455. check_input(x, repeat_times)
  3456. def get_attr_repeat_times(list_repeat_times):
  3457. attrs_repeat_times = []
  3458. for idx, times in enumerate(list_repeat_times):
  3459. if isinstance(times, Variable):
  3460. attrs_repeat_times.append(-1)
  3461. else:
  3462. attrs_repeat_times.append(times)
  3463. assert (
  3464. times > 0
  3465. ), "All elements in repeat_times must be positive for tile."
  3466. return attrs_repeat_times
  3467. helper = LayerHelper('tile', **locals())
  3468. inputs = {"X": [x]}
  3469. attrs = {}
  3470. if isinstance(repeat_times, Variable):
  3471. repeat_times.stop_gradient = True
  3472. inputs['RepeatTimes'] = repeat_times
  3473. attrs['repeat_times'] = [-1]
  3474. elif isinstance(repeat_times, (list, tuple)):
  3475. attrs['repeat_times'] = get_attr_repeat_times(repeat_times)
  3476. if paddle.utils._contain_var(repeat_times):
  3477. inputs[
  3478. 'repeat_times_tensor'
  3479. ] = paddle.utils._convert_to_tensor_list(repeat_times)
  3480. dtype = helper.input_dtype(input_param_name='x')
  3481. out = helper.create_variable_for_type_inference(dtype)
  3482. helper.append_op(
  3483. type='tile', inputs=inputs, outputs={'Out': out}, attrs=attrs
  3484. )
  3485. return out
  3486. def expand_as(x, y, name=None):
  3487. """
  3488. Expand the input tensor ``x`` to the same shape as the input tensor ``y``.
  3489. Both the number of dimensions of ``x`` and ``y`` must be less than or equal to 6, and the number of dimensions of ``y`` must be greater than or equal to that of ``x``. The dimension to expand must have a value of 0.
  3490. Args:
  3491. x (Tensor): The input tensor, its data type is bool, float32, float64, int32 or int64.
  3492. y (Tensor): The input tensor that gives the shape to expand to.
  3493. name (str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`.
  3494. Returns:
  3495. N-D Tensor, A Tensor with the same shape as ``y``. The data type is the same as ``x``.
  3496. Examples:
  3497. .. code-block:: python
  3498. >>> import paddle
  3499. >>> data_x = paddle.to_tensor([1, 2, 3], 'int32')
  3500. >>> data_y = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], 'int32')
  3501. >>> out = paddle.expand_as(data_x, data_y)
  3502. >>> print(out)
  3503. Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
  3504. [[1, 2, 3],
  3505. [1, 2, 3]])
  3506. """
  3507. if in_dynamic_or_pir_mode():
  3508. return _C_ops.expand_as(x, None, y.shape)
  3509. else:
  3510. check_variable_and_dtype(
  3511. x,
  3512. 'x',
  3513. [
  3514. 'bool',
  3515. 'float32',
  3516. 'float64',
  3517. 'int32',
  3518. 'int64',
  3519. 'float16',
  3520. 'uint16',
  3521. ],
  3522. 'expand_as',
  3523. )
  3524. check_type(y, 'y', Variable, 'expand_as')
  3525. if convert_dtype(x.dtype) == 'bool' and not x.stop_gradient:
  3526. raise ValueError(
  3527. "When the data type of input 'x' for expand_as is bool, "
  3528. "you must set its stop_gradient to be False by "
  3529. "some_var.stop_gradient = True, supporting "
  3530. "some_var as the input 'x'."
  3531. )
  3532. inputs = {"X": [x], "Y": [y]}
  3533. helper = LayerHelper('expand_as', **locals())
  3534. dtype = helper.input_dtype(input_param_name='x')
  3535. out = helper.create_variable_for_type_inference(dtype)
  3536. helper.append_op(
  3537. type='expand_as_v2',
  3538. inputs=inputs,
  3539. attrs={'target_shape': y.shape},
  3540. outputs={'Out': out},
  3541. )
  3542. return out
  3543. def broadcast_to(x, shape, name=None):
  3544. """
  3545. Broadcast the input tensor to a given shape.
  3546. Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. The dimension to broadcast to must have a value 0.
  3547. Args:
  3548. x (Tensor): The input tensor, its data type is bool, float16, float32, float64, int32, int64, uint8 or uint16.
  3549. shape (list|tuple|Tensor): The result shape after broadcasting. The data type is int32. If shape is a list or tuple, all its elements
  3550. should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32.
  3551. The value -1 in shape means keeping the corresponding dimension unchanged.
  3552. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  3553. Returns:
  3554. N-D Tensor, A Tensor with the given shape. The data type is the same as ``x``.
  3555. Examples:
  3556. .. code-block:: python
  3557. >>> import paddle
  3558. >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
  3559. >>> out = paddle.broadcast_to(data, shape=[2, 3])
  3560. >>> print(out)
  3561. Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
  3562. [[1, 2, 3],
  3563. [1, 2, 3]])
  3564. """
  3565. return expand(x, shape, name)
  3566. def expand(x, shape, name=None):
  3567. """
  3568. Expand the input tensor to a given shape.
  3569. Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. And the number of dimensions of ``x`` should be less than the number of elements in ``shape``. The dimension to expand must have a value 0.
  3570. Args:
  3571. x (Tensor): The input Tensor, its data type is bool, float16, float32, float64, int32, int64, uint8, uint16, complex64 or complex128.
  3572. shape (list|tuple|Tensor): The result shape after expanding. The data type is int32. If shape is a list or tuple, all its elements
  3573. should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32.
  3574. The value -1 in shape means keeping the corresponding dimension unchanged.
  3575. name (str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name` .
  3576. Returns:
  3577. N-D Tensor, A Tensor with the given shape. The data type is the same as ``x``.
  3578. Examples:
  3579. .. code-block:: python
  3580. >>> import paddle
  3581. >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
  3582. >>> out = paddle.expand(data, shape=[2, 3])
  3583. >>> print(out)
  3584. Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
  3585. [[1, 2, 3],
  3586. [1, 2, 3]])
  3587. """
  3588. if in_dynamic_mode():
  3589. return _C_ops.expand(x, shape)
  3590. elif in_pir_mode():
  3591. if convert_dtype(x.dtype) == 'bool' and not x.stop_gradient:
  3592. raise ValueError(
  3593. "When the data type of input 'x' for expand is bool, "
  3594. "you must set its stop_gradient to be False by "
  3595. "some_var.stop_gradient = True, supporting "
  3596. "some_var as the input."
  3597. )
  3598. if isinstance(shape, paddle.pir.Value):
  3599. shape.stop_gradient = True
  3600. elif isinstance(shape, (list, tuple)):
  3601. if paddle.utils._contain_var(shape):
  3602. shape = paddle.utils.get_int_tensor_list(shape)
  3603. else:
  3604. raise TypeError("Shape only supports Value, or list, or tuple.")
  3605. return _C_ops.expand(x, shape)
  3606. else:
  3607. if isinstance(shape, Variable):
  3608. assert len(shape.shape) == 1, 'shape must be a 1-D Tensor.'
  3609. else:
  3610. for elem in shape:
  3611. if isinstance(elem, Variable):
  3612. assert (
  3613. elem.numel() == 1
  3614. ), 'Elements in shape must be Tensor with one element or integers.'
  3615. else:
  3616. type_tuple = (int, np.int32, np.int64)
  3617. assert isinstance(
  3618. elem, type_tuple
  3619. ), 'Elements in shape must be Tensor with one element or integers.'
  3620. check_variable_and_dtype(
  3621. x,
  3622. 'x',
  3623. [
  3624. 'bool',
  3625. 'float16',
  3626. 'float32',
  3627. 'float64',
  3628. 'int32',
  3629. 'int64',
  3630. 'uint8',
  3631. 'uint16',
  3632. 'complex64',
  3633. 'complex128',
  3634. ],
  3635. 'expand',
  3636. )
  3637. check_type(shape, 'shape', (list, tuple, Variable), 'expand')
  3638. if convert_dtype(x.dtype) == 'bool' and not x.stop_gradient:
  3639. raise ValueError(
  3640. "When the data type of input 'x' for expand is bool, "
  3641. "you must set its stop_gradient to be False by "
  3642. "some_var.stop_gradient = True, supporting "
  3643. "some_var as the input."
  3644. )
  3645. inputs = {"X": [x]}
  3646. attrs = {}
  3647. helper = LayerHelper('expand', **locals())
  3648. def get_attr_expand_shape(list_expand_shape):
  3649. attrs_expand_shape = []
  3650. for idx, shape in enumerate(list_expand_shape):
  3651. if isinstance(shape, Variable):
  3652. attrs_expand_shape.append(-2)
  3653. else:
  3654. attrs_expand_shape.append(shape)
  3655. assert (
  3656. shape > 0 or shape == -1
  3657. ), "All elements in shape of expand must be positive or -1."
  3658. return attrs_expand_shape
  3659. if isinstance(shape, Variable):
  3660. shape.stop_gradient = True
  3661. inputs['Shape'] = shape
  3662. elif isinstance(shape, (list, tuple)):
  3663. attrs['shape'] = get_attr_expand_shape(shape)
  3664. if paddle.utils._contain_var(shape):
  3665. inputs[
  3666. 'expand_shapes_tensor'
  3667. ] = paddle.utils._convert_to_tensor_list(shape)
  3668. dtype = helper.input_dtype(input_param_name='x')
  3669. out = helper.create_variable_for_type_inference(dtype)
  3670. helper.append_op(
  3671. type='expand_v2', inputs=inputs, outputs={'Out': out}, attrs=attrs
  3672. )
  3673. return out
  3674. def reshape(x, shape, name=None):
  3675. """
  3676. Changes the shape of ``x`` without changing its data.
  3677. Note that the output Tensor will share data with origin Tensor and doesn't
  3678. have a Tensor copy in ``dygraph`` mode.
  3679. If you want to use the Tensor copy version, please use `Tensor.clone` like
  3680. ``reshape_clone_x = x.reshape([-1]).clone()``.
  3681. Some tricks exist when specifying the target shape.
  3682. - 1. -1 means the value of this dimension is inferred from the total element number of x and remaining dimensions. Thus one and only one dimension can be set -1.
  3683. - 2. 0 means the actual dimension value is going to be copied from the corresponding dimension of x. The index of 0s in shape can not exceed the dimension of x.
  3684. Here are some examples to explain it.
  3685. - 1. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [6, 8], the reshape operator will transform x into a 2-D tensor with shape [6, 8] and leaving x's data unchanged.
  3686. - 2. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape specified is [2, 3, -1, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 3, 4, 2] and leaving x's data unchanged. In this case, one dimension of the target shape is set to -1, the value of this dimension is inferred from the total element number of x and remaining dimensions.
  3687. - 3. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [-1, 0, 3, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 4, 3, 2] and leaving x's data unchanged. In this case, besides -1, 0 means the actual dimension value is going to be copied from the corresponding dimension of x.
  3688. The following figure illustrates the first example -- a 3D tensor of shape [2, 4, 6] is transformed into a 2D tensor of shape [6, 8], during which the order and values of the elements in the tensor remain unchanged. The elements in the two subdiagrams correspond to each other, clearly demonstrating how the reshape API works.
  3689. .. image:: https://githubraw.cdn.bcebos.com/PaddlePaddle/docs/develop/docs/images/api_legend/reshape.png
  3690. :width: 800
  3691. :alt: legend of reshape API
  3692. :align: center
  3693. Args:
  3694. x (Tensor): An N-D Tensor. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
  3695. shape (list|tuple|Tensor): Define the target shape. At most one dimension of the target shape can be -1.
  3696. The data type is ``int32`` . If ``shape`` is a list or tuple, each element of it should be integer or Tensor with shape [].
  3697. If ``shape`` is a Tensor, it should be an 1-D Tensor .
  3698. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  3699. Returns:
  3700. Tensor, A reshaped Tensor with the same data type as ``x``.
  3701. Examples:
  3702. .. code-block:: python
  3703. >>> import paddle
  3704. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  3705. >>> positive_four = paddle.full([1], 4, "int32")
  3706. >>> out = paddle.reshape(x, [-1, 0, 3, 2])
  3707. >>> print(out.shape)
  3708. [2, 4, 3, 2]
  3709. >>> out = paddle.reshape(x, shape=[positive_four, 12])
  3710. >>> print(out.shape)
  3711. [4, 12]
  3712. >>> shape_tensor = paddle.to_tensor([8, 6], dtype=paddle.int32)
  3713. >>> out = paddle.reshape(x, shape=shape_tensor)
  3714. >>> print(out.shape)
  3715. [8, 6]
  3716. >>> # out shares data with x in dygraph mode
  3717. >>> x[0, 0, 0] = 10.
  3718. >>> print(out[0, 0])
  3719. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  3720. 10.)
  3721. """
  3722. def get_attr_shape(list_shape):
  3723. unk_dim_idx = -1
  3724. attrs_shape = []
  3725. for dim_idx, dim_size in enumerate(list_shape):
  3726. if isinstance(dim_size, (Variable, paddle.pir.Value)):
  3727. attrs_shape.append(-1)
  3728. else:
  3729. attrs_shape.append(dim_size)
  3730. if dim_size == -1:
  3731. assert unk_dim_idx == -1, (
  3732. "Only one dimension value of 'shape' in reshape can "
  3733. "be -1. But received shape[%d] is also -1.\n"
  3734. "\n\t# N = x.shape()[2]\t\t# N is an int. "
  3735. "(NOT recommend under @to_static)\n\tN = paddle.shape(x)[2]\t\t"
  3736. "# N is a Tensor. (Recommend)\n\tz = paddle.reshape([N, -1, 4])"
  3737. "\t# z.shape is [-1, -1, 4]\n\n"
  3738. " If your target shape in Reshape represents dynamic shape, "
  3739. "please turn it into a Tensor under @to_static. See above example for details."
  3740. % dim_idx
  3741. )
  3742. unk_dim_idx = dim_idx
  3743. elif dim_size == 0:
  3744. assert dim_idx < len(x.shape), (
  3745. "The index of 0 in `shape` must be less than "
  3746. "the input tensor X's dimensions. "
  3747. "But received shape[%d] = 0, X's dimensions = %d."
  3748. % (dim_idx, len(x.shape))
  3749. )
  3750. else:
  3751. assert dim_size > 0, (
  3752. "Each dimension value of 'shape' in reshape must not "
  3753. "be negative except one unknown dimension. "
  3754. "But received shape[%d] = %s."
  3755. % (dim_idx, str(dim_size))
  3756. )
  3757. return attrs_shape
  3758. if in_dynamic_mode():
  3759. if isinstance(shape, (list, tuple)):
  3760. new_shape = []
  3761. for ele in shape:
  3762. if isinstance(ele, core.eager.Tensor):
  3763. new_shape.append(ele.item())
  3764. else:
  3765. new_shape.append(ele)
  3766. if new_shape == x.shape:
  3767. out = x
  3768. else:
  3769. out = _C_ops.reshape(x, new_shape)
  3770. elif isinstance(shape, core.eager.Tensor):
  3771. shape.stop_gradient = True
  3772. out = _C_ops.reshape(x, shape)
  3773. else:
  3774. raise ValueError(
  3775. "shape must be an instance of `list`, `tuple` `Variable`,"
  3776. f" got '{type(shape)}.'"
  3777. )
  3778. return out
  3779. elif in_pir_mode():
  3780. check_variable_and_dtype(
  3781. x,
  3782. 'x',
  3783. [
  3784. 'float16',
  3785. 'float32',
  3786. 'float64',
  3787. 'int8',
  3788. 'uint8',
  3789. 'int16',
  3790. 'int32',
  3791. 'int64',
  3792. 'bool',
  3793. 'uint16',
  3794. 'complex64',
  3795. 'complex128',
  3796. ],
  3797. 'reshape',
  3798. )
  3799. check_type(shape, 'shape', (list, tuple, paddle.pir.Value), 'reshape')
  3800. if isinstance(shape, (list, tuple)):
  3801. if paddle.utils._contain_var(shape):
  3802. new_shape = paddle.utils.get_int_tensor_list(shape)
  3803. else:
  3804. new_shape = get_attr_shape(shape)
  3805. out = _C_ops.reshape(x, new_shape)
  3806. elif isinstance(shape, paddle.pir.Value):
  3807. shape.stop_gradient = True
  3808. out = _C_ops.reshape(x, shape)
  3809. else:
  3810. raise ValueError(
  3811. "shape must be an instance of `list`, `tuple` `Value(in pir mode)`,"
  3812. f" got '{type(shape)}.'"
  3813. )
  3814. return out
  3815. else:
  3816. check_variable_and_dtype(
  3817. x,
  3818. 'x',
  3819. [
  3820. 'float16',
  3821. 'float32',
  3822. 'float64',
  3823. 'int16',
  3824. 'int32',
  3825. 'int64',
  3826. 'bool',
  3827. 'uint16',
  3828. 'int8',
  3829. 'uint8',
  3830. 'complex64',
  3831. 'complex128',
  3832. ],
  3833. 'reshape',
  3834. )
  3835. check_type(shape, 'shape', (list, tuple, Variable), 'reshape')
  3836. inputs = {"X": x}
  3837. attrs = {}
  3838. if isinstance(shape, Variable):
  3839. shape.stop_gradient = True
  3840. inputs["Shape"] = shape
  3841. elif isinstance(shape, (list, tuple)):
  3842. attrs["shape"] = get_attr_shape(shape)
  3843. if paddle.utils._contain_var(shape):
  3844. inputs['ShapeTensor'] = paddle.utils._convert_to_tensor_list(
  3845. shape
  3846. )
  3847. helper = LayerHelper("reshape2", **locals())
  3848. out = helper.create_variable_for_type_inference(dtype=x.dtype)
  3849. x_shape = helper.create_variable_for_type_inference(dtype=x.dtype)
  3850. helper.append_op(
  3851. type="reshape2",
  3852. inputs=inputs,
  3853. attrs=attrs,
  3854. outputs={"Out": out, "XShape": x_shape},
  3855. )
  3856. return out
  3857. def masked_scatter(x, mask, value, name=None):
  3858. """
  3859. Copies elements from `value` into `x` tensor at positions where the `mask` is True.
  3860. Elements from source are copied into `x` starting at position 0 of `value` and continuing in order one-by-one for
  3861. each occurrence of `mask` being True. The shape of `mask` must be broadcastable with the shape of the underlying tensor.
  3862. The `value` should have at least as many elements as the number of ones in `mask`.
  3863. Args:
  3864. x (Tensor): An N-D Tensor. The data type is ``float16``, ``float32``, ``float64``, ``int32``,
  3865. ``int64`` or ``bfloat16``.
  3866. mask (Tensor): The boolean tensor indicate the position to be filled.
  3867. The data type of mask must be bool.
  3868. value (Tensor): The value used to fill the target tensor.
  3869. Supported data types are same as x.
  3870. name (str, optional): Name for the operation (optional, default is None). For more information,
  3871. please refer to :ref:`api_guide_Name`.
  3872. Returns:
  3873. Tensor, A reshaped Tensor with the same data type as ``x``.
  3874. Examples:
  3875. .. code-block:: python
  3876. >>> import paddle
  3877. >>> paddle.seed(2048)
  3878. >>> x = paddle.randn([2, 2])
  3879. >>> print(x)
  3880. Tensor(shape=[2, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  3881. [[-1.24725831, 0.03843464],
  3882. [-0.31660911, 0.04793844]])
  3883. >>> mask = paddle.to_tensor([[True, True], [False, False]])
  3884. >>> value = paddle.to_tensor([1, 2, 3, 4, 5,], dtype="float32")
  3885. >>> out = paddle.masked_scatter(x, mask, value)
  3886. >>> print(out)
  3887. Tensor(shape=[2, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  3888. [[1, 2],
  3889. [-0.31660911, 0.04793844]])
  3890. """
  3891. # make sure the dtype of x and value is the same
  3892. assert (
  3893. x.dtype == value.dtype
  3894. ), f'x and value must have the same dtype, but got x dtype is {x.dtype}, value dtype is {value.dtype}'
  3895. assert mask.dtype == paddle.bool
  3896. zeros_like_x = paddle.zeros_like(x, dtype=int)
  3897. mask = paddle.add(paddle.cast(mask, dtype="int"), zeros_like_x)
  3898. mask_prefix = paddle.clip(mask.cumsum() - 1, min=0)
  3899. if in_dynamic_mode():
  3900. assert (
  3901. mask_prefix[-1] <= value.numel()
  3902. ), f'mask true nums must be <= value size, but got mask true nums is {mask_prefix[-1].item()}, value size is {value.numel().item()}'
  3903. value = value.flatten()[mask_prefix].reshape(mask.shape)
  3904. mask = paddle.logical_not(mask.astype(bool))
  3905. return paddle.where(mask, x, value)
  3906. @inplace_apis_in_dygraph_only
  3907. def masked_scatter_(x, mask, value, name=None):
  3908. """
  3909. Inplace version of ``masked_scatter`` API, the output Tensor will be inplaced with input ``x``.
  3910. Please refer to :ref:`api_paddle_masked_scatter`.
  3911. """
  3912. assert (
  3913. x.dtype == value.dtype
  3914. ), f'x and value must have the same dtype, but got x dtype is {x.dtype}, value dtype is {value.dtype}'
  3915. assert mask.dtype == paddle.bool
  3916. zeros_like_x = paddle.zeros_like(x, dtype=int)
  3917. mask = paddle.add(paddle.cast(mask, dtype="int"), zeros_like_x)
  3918. mask_prefix = paddle.clip(mask.cumsum() - 1, min=0)
  3919. assert (
  3920. mask_prefix[-1] <= value.numel()
  3921. ), f'mask true nums must be <= value size, but got mask true nums is {mask_prefix[-1].item()}, value size is {value.numel().item()}'
  3922. value = value.flatten()[mask_prefix].reshape(mask.shape)
  3923. mask = paddle.logical_not(mask.astype(bool))
  3924. out = paddle.where_(mask, x, value)
  3925. return out
  3926. @inplace_apis_in_dygraph_only
  3927. def reshape_(x, shape, name=None):
  3928. """
  3929. Inplace version of ``reshape`` API, the output Tensor will be inplaced with input ``x``.
  3930. Please refer to :ref:`api_paddle_tensor_reshape`.
  3931. """
  3932. if in_dynamic_mode():
  3933. tmp_tensor_type = core.eager.Tensor
  3934. if isinstance(shape, (list, tuple)):
  3935. shape = [
  3936. item.item(0) if isinstance(item, tmp_tensor_type) else item
  3937. for item in shape
  3938. ]
  3939. if shape == x.shape:
  3940. out = x
  3941. else:
  3942. out = _C_ops.reshape_(x, shape)
  3943. elif isinstance(shape, tmp_tensor_type):
  3944. shape.stop_gradient = True
  3945. out = _C_ops.reshape_(x, shape)
  3946. else:
  3947. raise ValueError(
  3948. "shape must be an instance of `list`, `tuple` or `Variable`,"
  3949. f" got '{type(shape)}.'"
  3950. )
  3951. return out
  3952. def atleast_1d(*inputs, name=None):
  3953. """
  3954. Convert inputs to tensors and return the view with at least 1-dimension. Scalar inputs are converted,
  3955. one or high-dimensional inputs are preserved.
  3956. Args:
  3957. inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
  3958. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  3959. Returns:
  3960. One Tensor, if there is only one input.
  3961. List of Tensors, if there are more than one inputs.
  3962. Examples:
  3963. .. code-block:: python
  3964. >>> import paddle
  3965. >>> # one input
  3966. >>> x = paddle.to_tensor(123, dtype='int32')
  3967. >>> out = paddle.atleast_1d(x)
  3968. >>> print(out)
  3969. Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
  3970. [123])
  3971. >>> # more than one inputs
  3972. >>> x = paddle.to_tensor(123, dtype='int32')
  3973. >>> y = paddle.to_tensor([1.23], dtype='float32')
  3974. >>> out = paddle.atleast_1d(x, y)
  3975. >>> print(out)
  3976. [Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
  3977. [123]), Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
  3978. [1.23000002])]
  3979. >>> # more than 1-D input
  3980. >>> x = paddle.to_tensor(123, dtype='int32')
  3981. >>> y = paddle.to_tensor([[1.23]], dtype='float32')
  3982. >>> out = paddle.atleast_1d(x, y)
  3983. >>> print(out)
  3984. [Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
  3985. [123]), Tensor(shape=[1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  3986. [[1.23000002]])]
  3987. """
  3988. out = []
  3989. for input in inputs:
  3990. if not isinstance(
  3991. input,
  3992. (
  3993. paddle.Tensor,
  3994. paddle.base.framework.Variable,
  3995. paddle.base.libpaddle.pir.Value,
  3996. ),
  3997. ):
  3998. tensor = paddle.to_tensor(input)
  3999. else:
  4000. tensor = input
  4001. if tensor.dim() == 0:
  4002. result = tensor.reshape((1,))
  4003. else:
  4004. result = tensor
  4005. out.append(result)
  4006. if len(out) == 1:
  4007. return out[0]
  4008. else:
  4009. return out
  4010. def atleast_2d(*inputs, name=None):
  4011. """
  4012. Convert inputs to tensors and return the view with at least 2-dimension. Two or high-dimensional inputs are preserved.
  4013. Args:
  4014. inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
  4015. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  4016. Returns:
  4017. One Tensor, if there is only one input.
  4018. List of Tensors, if there are more than one inputs.
  4019. Examples:
  4020. .. code-block:: python
  4021. >>> import paddle
  4022. >>> # one input
  4023. >>> x = paddle.to_tensor(123, dtype='int32')
  4024. >>> out = paddle.atleast_2d(x)
  4025. >>> print(out)
  4026. Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4027. [[123]])
  4028. >>> # more than one inputs
  4029. >>> x = paddle.to_tensor(123, dtype='int32')
  4030. >>> y = paddle.to_tensor([1.23], dtype='float32')
  4031. >>> out = paddle.atleast_2d(x, y)
  4032. >>> print(out)
  4033. [Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4034. [[123]]), Tensor(shape=[1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  4035. [[1.23000002]])]
  4036. >>> # more than 2-D input
  4037. >>> x = paddle.to_tensor(123, dtype='int32')
  4038. >>> y = paddle.to_tensor([[[1.23]]], dtype='float32')
  4039. >>> out = paddle.atleast_2d(x, y)
  4040. >>> print(out)
  4041. [Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4042. [[123]]), Tensor(shape=[1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  4043. [[[1.23000002]]])]
  4044. """
  4045. out = []
  4046. for input in inputs:
  4047. if not isinstance(
  4048. input,
  4049. (
  4050. paddle.Tensor,
  4051. paddle.base.framework.Variable,
  4052. paddle.base.libpaddle.pir.Value,
  4053. ),
  4054. ):
  4055. tensor = paddle.to_tensor(input)
  4056. else:
  4057. tensor = input
  4058. if tensor.dim() == 0:
  4059. result = tensor.reshape((1, 1))
  4060. elif tensor.dim() == 1:
  4061. result = paddle.unsqueeze(tensor, axis=0)
  4062. else:
  4063. result = tensor
  4064. out.append(result)
  4065. if len(out) == 1:
  4066. return out[0]
  4067. else:
  4068. return out
  4069. def atleast_3d(*inputs, name=None):
  4070. """
  4071. Convert inputs to tensors and return the view with at least 3-dimension. Three or high-dimensional inputs are preserved.
  4072. Args:
  4073. inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
  4074. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  4075. Returns:
  4076. One Tensor, if there is only one input.
  4077. List of Tensors, if there are more than one inputs.
  4078. Examples:
  4079. .. code-block:: python
  4080. >>> import paddle
  4081. >>> # one input
  4082. >>> x = paddle.to_tensor(123, dtype='int32')
  4083. >>> out = paddle.atleast_3d(x)
  4084. >>> print(out)
  4085. Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4086. [[[123]]])
  4087. >>> # more than one inputs
  4088. >>> x = paddle.to_tensor(123, dtype='int32')
  4089. >>> y = paddle.to_tensor([1.23], dtype='float32')
  4090. >>> out = paddle.atleast_3d(x, y)
  4091. >>> print(out)
  4092. [Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4093. [[[123]]]), Tensor(shape=[1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  4094. [[[1.23000002]]])]
  4095. >>> # more than 3-D input
  4096. >>> x = paddle.to_tensor(123, dtype='int32')
  4097. >>> y = paddle.to_tensor([[[[1.23]]]], dtype='float32')
  4098. >>> out = paddle.atleast_3d(x, y)
  4099. >>> print(out)
  4100. [Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
  4101. [[[123]]]), Tensor(shape=[1, 1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
  4102. [[[[1.23000002]]]])]
  4103. """
  4104. out = []
  4105. for input in inputs:
  4106. if not isinstance(
  4107. input,
  4108. (
  4109. paddle.Tensor,
  4110. paddle.base.framework.Variable,
  4111. paddle.base.libpaddle.pir.Value,
  4112. ),
  4113. ):
  4114. tensor = paddle.to_tensor(input)
  4115. else:
  4116. tensor = input
  4117. if tensor.dim() == 0:
  4118. result = tensor.reshape((1, 1, 1))
  4119. elif tensor.dim() == 1:
  4120. result = paddle.unsqueeze(tensor, axis=[0, 2])
  4121. elif tensor.dim() == 2:
  4122. result = paddle.unsqueeze(tensor, axis=2)
  4123. else:
  4124. result = tensor
  4125. out.append(result)
  4126. if len(out) == 1:
  4127. return out[0]
  4128. else:
  4129. return out
  4130. def gather_nd(x, index, name=None):
  4131. """
  4132. This function is actually a high-dimensional extension of :code:`gather`
  4133. and supports for simultaneous indexing by multiple axes. :attr:`index` is a
  4134. K-dimensional integer tensor, which is regarded as a (K-1)-dimensional
  4135. tensor of :attr:`index` into :attr:`input`, where each element defines
  4136. a slice of params:
  4137. .. math::
  4138. output[(i_0, ..., i_{K-2})] = input[index[(i_0, ..., i_{K-2})]]
  4139. Obviously, :code:`index.shape[-1] <= input.rank` . And, the output tensor has
  4140. shape :code:`index.shape[:-1] + input.shape[index.shape[-1]:]` .
  4141. .. code-block:: text
  4142. Given:
  4143. x = [[[ 0, 1, 2, 3],
  4144. [ 4, 5, 6, 7],
  4145. [ 8, 9, 10, 11]],
  4146. [[12, 13, 14, 15],
  4147. [16, 17, 18, 19],
  4148. [20, 21, 22, 23]]]
  4149. x.shape = (2, 3, 4)
  4150. * Case 1:
  4151. index = [[1]]
  4152. gather_nd(x, index)
  4153. = [x[1, :, :]]
  4154. = [[12, 13, 14, 15],
  4155. [16, 17, 18, 19],
  4156. [20, 21, 22, 23]]
  4157. * Case 2:
  4158. index = [[0,2]]
  4159. gather_nd(x, index)
  4160. = [x[0, 2, :]]
  4161. = [8, 9, 10, 11]
  4162. * Case 3:
  4163. index = [[1, 2, 3]]
  4164. gather_nd(x, index)
  4165. = [x[1, 2, 3]]
  4166. = [23]
  4167. Args:
  4168. x (Tensor): The input Tensor which it's data type should be bool, float16, float32, float64, int32, int64.
  4169. index (Tensor): The index input with rank > 1, index.shape[-1] <= input.rank.
  4170. Its dtype should be int32, int64.
  4171. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  4172. Returns:
  4173. output (Tensor), A tensor with the shape index.shape[:-1] + input.shape[index.shape[-1]:]
  4174. Examples:
  4175. .. code-block:: python
  4176. >>> import paddle
  4177. >>> x = paddle.to_tensor([[[1, 2], [3, 4], [5, 6]],
  4178. ... [[7, 8], [9, 10], [11, 12]]])
  4179. >>> index = paddle.to_tensor([[0, 1]])
  4180. >>> output = paddle.gather_nd(x, index)
  4181. >>> print(output)
  4182. Tensor(shape=[1, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
  4183. [[3, 4]])
  4184. """
  4185. if in_dynamic_or_pir_mode():
  4186. return _C_ops.gather_nd(x, index)
  4187. else:
  4188. check_variable_and_dtype(
  4189. x,
  4190. 'x',
  4191. [
  4192. 'bool',
  4193. 'float16',
  4194. 'uint16',
  4195. 'float32',
  4196. 'float64',
  4197. 'int16',
  4198. 'int32',
  4199. 'int64',
  4200. ],
  4201. 'gather_np',
  4202. )
  4203. check_variable_and_dtype(
  4204. index, 'index', ['int32', 'int64'], 'gather_np'
  4205. )
  4206. helper = LayerHelper('gather_nd', **locals())
  4207. dtype = helper.input_dtype()
  4208. output = helper.create_variable_for_type_inference(dtype)
  4209. helper.append_op(
  4210. type="gather_nd",
  4211. inputs={"X": x, "Index": index},
  4212. outputs={"Out": output},
  4213. )
  4214. return output
  4215. def strided_slice(x, axes, starts, ends, strides, name=None):
  4216. """
  4217. This operator produces a slice of ``x`` along multiple axes. Similar to numpy:
  4218. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
  4219. Slice uses ``axes``, ``starts`` and ``ends`` attributes to specify the start and
  4220. end dimension for each axis in the list of axes and Slice uses this information
  4221. to slice the input data tensor. If a negative value is passed to
  4222. ``starts`` or ``ends`` such as :math:`-i`, it represents the reverse position of the
  4223. axis :math:`i-1` th(here 0 is the initial position). The ``strides`` represents steps of
  4224. slicing and if the ``strides`` is negative, slice operation is in the opposite direction.
  4225. If the value passed to ``starts`` or ``ends`` is greater than n
  4226. (the number of elements in this dimension), it represents n.
  4227. For slicing to the end of a dimension with unknown size, it is recommended
  4228. to pass in INT_MAX. The size of ``axes`` must be equal to ``starts`` , ``ends`` and ``strides``.
  4229. Following examples will explain how strided_slice works:
  4230. .. code-block:: text
  4231. Case1:
  4232. Given:
  4233. data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
  4234. axes = [0, 1]
  4235. starts = [1, 0]
  4236. ends = [2, 3]
  4237. strides = [1, 1]
  4238. Then:
  4239. result = [ [5, 6, 7], ]
  4240. Case2:
  4241. Given:
  4242. data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
  4243. axes = [0, 1]
  4244. starts = [0, 1]
  4245. ends = [2, 0]
  4246. strides = [1, -1]
  4247. Then:
  4248. result = [ [8, 7, 6], ]
  4249. Case3:
  4250. Given:
  4251. data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
  4252. axes = [0, 1]
  4253. starts = [0, 1]
  4254. ends = [-1, 1000]
  4255. strides = [1, 3]
  4256. Then:
  4257. result = [ [2], ]
  4258. Args:
  4259. x (Tensor): An N-D ``Tensor``. The data type is ``bool``, ``float16``, ``float32``, ``float64``, ``int32`` or ``int64``.
  4260. axes (list|tuple): The data type is ``int32`` . Axes that `starts` and `ends` apply to.
  4261. It's optional. If it is not provides, it will be treated as :math:`[0,1,...,len(starts)-1]`.
  4262. starts (list|tuple|Tensor): The data type is ``int32`` . If ``starts`` is a list or tuple, the elements of it should be
  4263. integers or Tensors with shape []. If ``starts`` is an Tensor, it should be an 1-D Tensor.
  4264. It represents starting indices of corresponding axis in ``axes``.
  4265. ends (list|tuple|Tensor): The data type is ``int32`` . If ``ends`` is a list or tuple, the elements of it should be
  4266. integers or Tensors with shape []. If ``ends`` is an Tensor, it should be an 1-D Tensor.
  4267. It represents ending indices of corresponding axis in ``axes``.
  4268. strides (list|tuple|Tensor): The data type is ``int32`` . If ``strides`` is a list or tuple, the elements of it should be
  4269. integers or Tensors with shape []. If ``strides`` is an Tensor, it should be an 1-D Tensor.
  4270. It represents slice step of corresponding axis in ``axes``.
  4271. name(str, optional): The default value is None. Normally there is no need for user to set this property.
  4272. For more information, please refer to :ref:`api_guide_Name` .
  4273. Returns:
  4274. Tensor, A ``Tensor`` with the same dimension as ``x``. The data type is same as ``x``.
  4275. Examples:
  4276. .. code-block:: python
  4277. >>> import paddle
  4278. >>> x = paddle.zeros(shape=[3,4,5,6], dtype="float32")
  4279. >>> # example 1:
  4280. >>> # attr starts is a list which doesn't contain Tensor.
  4281. >>> axes = [1, 2, 3]
  4282. >>> starts = [-3, 0, 2]
  4283. >>> ends = [3, 2, 4]
  4284. >>> strides_1 = [1, 1, 1]
  4285. >>> strides_2 = [1, 1, 2]
  4286. >>> sliced_1 = paddle.strided_slice(x, axes=axes, starts=starts, ends=ends, strides=strides_1)
  4287. >>> # sliced_1 is x[:, 1:3:1, 0:2:1, 2:4:1].
  4288. >>> # example 2:
  4289. >>> # attr starts is a list which contain tensor Tensor.
  4290. >>> minus_3 = paddle.full(shape=[1], fill_value=-3, dtype='int32')
  4291. >>> sliced_2 = paddle.strided_slice(x, axes=axes, starts=[minus_3, 0, 2], ends=ends, strides=strides_2)
  4292. >>> # sliced_2 is x[:, 1:3:1, 0:2:1, 2:4:2].
  4293. """
  4294. if in_dynamic_or_pir_mode():
  4295. return _C_ops.strided_slice(x, axes, starts, ends, strides)
  4296. else:
  4297. helper = LayerHelper('strided_slice', **locals())
  4298. check_variable_and_dtype(
  4299. x,
  4300. 'x',
  4301. [
  4302. 'bool',
  4303. 'float16',
  4304. 'uint16',
  4305. 'float32',
  4306. 'float64',
  4307. 'int32',
  4308. 'int64',
  4309. ],
  4310. 'strided_slice',
  4311. )
  4312. check_type(axes, 'axes', (list, tuple), 'strided_slice')
  4313. check_type(starts, 'starts', (list, tuple, Variable), 'strided_slice')
  4314. check_type(ends, 'ends', (list, tuple, Variable), 'strided_slice')
  4315. check_type(strides, 'strides', (list, tuple, Variable), 'strided_slice')
  4316. def check_list_elements_dtype(list_input, input_name):
  4317. if isinstance(list_input, Variable):
  4318. check_dtype(
  4319. list_input.dtype,
  4320. input_name,
  4321. ['int32', 'int64'],
  4322. 'strided_slice',
  4323. )
  4324. else:
  4325. for i, var in enumerate(list_input):
  4326. var_name = input_name + '[' + str(i) + ']'
  4327. if isinstance(var, Variable):
  4328. check_dtype(
  4329. var.dtype, var_name, ['int32'], 'strided_slice'
  4330. )
  4331. check_list_elements_dtype(axes, 'axes')
  4332. check_list_elements_dtype(starts, 'starts')
  4333. check_list_elements_dtype(ends, 'ends')
  4334. check_list_elements_dtype(strides, 'strides')
  4335. def get_new_list_tensor(old_list):
  4336. new_list_tensor = []
  4337. for dim in old_list:
  4338. if isinstance(dim, Variable):
  4339. dim.stop_gradient = True
  4340. new_list_tensor.append(dim)
  4341. else:
  4342. assert isinstance(dim, int)
  4343. temp_out = helper.create_variable_for_type_inference(
  4344. 'int32'
  4345. )
  4346. fill_constant(
  4347. [1], 'int32', dim, force_cpu=True, out=temp_out
  4348. )
  4349. new_list_tensor.append(temp_out)
  4350. return new_list_tensor
  4351. inputs = {'Input': x}
  4352. attrs = {'axes': axes}
  4353. infer_flags = [1 for i in range(len(axes))]
  4354. # starts
  4355. if isinstance(starts, Variable):
  4356. starts.stop_gradient = True
  4357. inputs['StartsTensor'] = starts
  4358. elif isinstance(starts, (list, tuple)):
  4359. attrs['starts'] = []
  4360. if paddle.utils._contain_var(starts):
  4361. inputs['StartsTensorList'] = get_new_list_tensor(starts)
  4362. for i, dim in enumerate(starts):
  4363. if isinstance(dim, Variable):
  4364. attrs['starts'].append(-1)
  4365. infer_flags[i] = -1
  4366. else:
  4367. attrs['starts'].append(dim)
  4368. else:
  4369. attrs['starts'] = starts
  4370. # ends
  4371. if isinstance(ends, Variable):
  4372. ends.stop_gradient = True
  4373. inputs['EndsTensor'] = ends
  4374. elif isinstance(ends, (list, tuple)):
  4375. attrs['ends'] = []
  4376. if paddle.utils._contain_var(ends):
  4377. inputs['EndsTensorList'] = get_new_list_tensor(ends)
  4378. for i, dim in enumerate(ends):
  4379. if isinstance(dim, Variable):
  4380. attrs['ends'].append(-1)
  4381. infer_flags[i] = -1
  4382. else:
  4383. attrs['ends'].append(dim)
  4384. else:
  4385. attrs['ends'] = ends
  4386. # strides
  4387. if isinstance(strides, Variable):
  4388. strides.stop_gradient = True
  4389. inputs['StridesTensor'] = strides
  4390. elif isinstance(strides, (list, tuple)):
  4391. attrs['strides'] = []
  4392. if paddle.utils._contain_var(strides):
  4393. inputs['StridesTensorList'] = get_new_list_tensor(strides)
  4394. for i, dim in enumerate(strides):
  4395. if isinstance(dim, Variable):
  4396. attrs['strides'].append(-1)
  4397. infer_flags[i] = -1
  4398. else:
  4399. attrs['strides'].append(dim)
  4400. else:
  4401. attrs['strides'] = strides
  4402. attrs['infer_flags'] = infer_flags
  4403. out = helper.create_variable_for_type_inference(
  4404. dtype=helper.input_dtype('x')
  4405. )
  4406. helper.append_op(
  4407. type='strided_slice',
  4408. inputs=inputs,
  4409. attrs=attrs,
  4410. outputs={'Out': out},
  4411. )
  4412. return out
  4413. def tensordot(x, y, axes=2, name=None):
  4414. r"""
  4415. This function computes a contraction, which sum the product of elements from two tensors along the given axes.
  4416. Args:
  4417. x (Tensor): The left tensor for contraction with data type ``float16`` or ``float32`` or ``float64``.
  4418. y (Tensor): The right tensor for contraction with the same data type as ``x``.
  4419. axes (int|tuple|list|Tensor, optional): The axes to contract for ``x`` and ``y``, defaulted to integer ``2``.
  4420. 1. It could be a non-negative integer ``n``,
  4421. in which the function will sum over the last ``n`` axes of ``x`` and the first ``n`` axes of ``y`` in order.
  4422. 2. It could be a 1-d tuple or list with data type ``int``, in which ``x`` and ``y`` will be contracted along the same given axes.
  4423. For example, ``axes`` =[0, 1] applies contraction along the first two axes for ``x`` and the first two axes for ``y``.
  4424. 3. It could be a tuple or list containing one or two 1-d tuple|list|Tensor with data type ``int``.
  4425. When containing one tuple|list|Tensor, the data in tuple|list|Tensor specified the same axes for ``x`` and ``y`` to contract.
  4426. When containing two tuple|list|Tensor, the first will be applied to ``x`` and the second to ``y``.
  4427. When containing more than two tuple|list|Tensor, only the first two axis sequences will be used while the others will be ignored.
  4428. 4. It could be a tensor, in which the ``axes`` tensor will be translated to a python list
  4429. and applied the same rules described above to determine the contraction axes.
  4430. Note that the ``axes`` with Tensor type is ONLY available in Dygraph mode.
  4431. name(str, optional): The default value is None. Normally there is no need for user to set this property.
  4432. For more information, please refer to :ref:`api_guide_Name` .
  4433. Return:
  4434. Output (Tensor), The contraction result with the same data type as ``x`` and ``y``.
  4435. In general, :math:`output.ndim = x.ndim + y.ndim - 2 \times n_{axes}`, where :math:`n_{axes}` denotes the number of axes to be contracted.
  4436. NOTES:
  4437. 1. This function supports tensor broadcast,
  4438. the size in the corresponding dimensions of ``x`` and ``y`` should be equal, or applies to the broadcast rules.
  4439. 2. This function also supports axes expansion,
  4440. when the two given axis sequences for ``x`` and ``y`` are of different lengths,
  4441. the shorter sequence will expand the same axes as the longer one at the end.
  4442. For example, if ``axes`` =[[0, 1, 2, 3], [1, 0]],
  4443. the axis sequence for ``x`` is [0, 1, 2, 3],
  4444. while the corresponding axis sequences for ``y`` will be expanded from [1, 0] to [1, 0, 2, 3].
  4445. Examples:
  4446. .. code-block:: python
  4447. >>> import paddle
  4448. >>> data_type = 'float64'
  4449. >>> # For two 2-d tensor x and y, the case axes=0 is equivalent to outer product.
  4450. >>> # Note that tensordot supports empty axis sequence, so all the axes=0, axes=[], axes=[[]], and axes=[[],[]] are equivalent cases.
  4451. >>> x = paddle.arange(4, dtype=data_type).reshape([2, 2])
  4452. >>> y = paddle.arange(4, dtype=data_type).reshape([2, 2])
  4453. >>> z = paddle.tensordot(x, y, axes=0)
  4454. >>> print(z)
  4455. Tensor(shape=[2, 2, 2, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
  4456. [[[[0., 0.],
  4457. [0., 0.]],
  4458. [[0., 1.],
  4459. [2., 3.]]],
  4460. [[[0., 2.],
  4461. [4., 6.]],
  4462. [[0., 3.],
  4463. [6., 9.]]]])
  4464. >>> # For two 1-d tensor x and y, the case axes=1 is equivalent to inner product.
  4465. >>> x = paddle.arange(10, dtype=data_type)
  4466. >>> y = paddle.arange(10, dtype=data_type)
  4467. >>> z1 = paddle.tensordot(x, y, axes=1)
  4468. >>> z2 = paddle.dot(x, y)
  4469. >>> print(z1)
  4470. Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
  4471. 285.)
  4472. >>> print(z2)
  4473. Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
  4474. 285.)
  4475. >>> # For two 2-d tensor x and y, the case axes=1 is equivalent to matrix multiplication.
  4476. >>> x = paddle.arange(6, dtype=data_type).reshape([2, 3])
  4477. >>> y = paddle.arange(12, dtype=data_type).reshape([3, 4])
  4478. >>> z1 = paddle.tensordot(x, y, axes=1)
  4479. >>> z2 = paddle.matmul(x, y)
  4480. >>> print(z1)
  4481. Tensor(shape=[2, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
  4482. [[20., 23., 26., 29.],
  4483. [56., 68., 80., 92.]])
  4484. >>> print(z2)
  4485. Tensor(shape=[2, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
  4486. [[20., 23., 26., 29.],
  4487. [56., 68., 80., 92.]])
  4488. >>> # When axes is a 1-d int list, x and y will be contracted along the same given axes.
  4489. >>> # Note that axes=[1, 2] is equivalent to axes=[[1, 2]], axes=[[1, 2], []], axes=[[1, 2], [1]], and axes=[[1, 2], [1, 2]].
  4490. >>> x = paddle.arange(24, dtype=data_type).reshape([2, 3, 4])
  4491. >>> y = paddle.arange(36, dtype=data_type).reshape([3, 3, 4])
  4492. >>> z = paddle.tensordot(x, y, axes=[1, 2])
  4493. >>> print(z)
  4494. Tensor(shape=[2, 3], dtype=float64, place=Place(cpu), stop_gradient=True,
  4495. [[506. , 1298., 2090.],
  4496. [1298., 3818., 6338.]])
  4497. >>> # When axes is a list containing two 1-d int list, the first will be applied to x and the second to y.
  4498. >>> x = paddle.arange(60, dtype=data_type).reshape([3, 4, 5])
  4499. >>> y = paddle.arange(24, dtype=data_type).reshape([4, 3, 2])
  4500. >>> z = paddle.tensordot(x, y, axes=([1, 0], [0, 1]))
  4501. >>> print(z)
  4502. Tensor(shape=[5, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
  4503. [[4400., 4730.],
  4504. [4532., 4874.],
  4505. [4664., 5018.],
  4506. [4796., 5162.],
  4507. [4928., 5306.]])
  4508. >>> # Thanks to the support of axes expansion, axes=[[0, 1, 3, 4], [1, 0, 3, 4]] can be abbreviated as axes= [[0, 1, 3, 4], [1, 0]].
  4509. >>> x = paddle.arange(720, dtype=data_type).reshape([2, 3, 4, 5, 6])
  4510. >>> y = paddle.arange(720, dtype=data_type).reshape([3, 2, 4, 5, 6])
  4511. >>> z = paddle.tensordot(x, y, axes=[[0, 1, 3, 4], [1, 0]])
  4512. >>> print(z)
  4513. Tensor(shape=[4, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
  4514. [[23217330., 24915630., 26613930., 28312230.],
  4515. [24915630., 26775930., 28636230., 30496530.],
  4516. [26613930., 28636230., 30658530., 32680830.],
  4517. [28312230., 30496530., 32680830., 34865130.]])
  4518. """
  4519. op_type = 'tensordot'
  4520. input_dtype = ['float16', 'float32', 'float64']
  4521. check_variable_and_dtype(x, 'x', input_dtype, op_type)
  4522. check_variable_and_dtype(y, 'y', input_dtype, op_type)
  4523. check_type(
  4524. axes, 'axes', (int, tuple, list, Variable, paddle.pir.Value), op_type
  4525. )
  4526. def _var_to_list(var):
  4527. if in_dynamic_mode():
  4528. return tolist(var)
  4529. raise TypeError(
  4530. "The 'axes' with type 'Tensor' in "
  4531. + op_type
  4532. + " is not available in static graph mode, "
  4533. "please convert its type to int|Tuple|List, or use dynamic graph mode."
  4534. )
  4535. axes_x = []
  4536. axes_y = []
  4537. if np.issubdtype(type(axes), np.integer):
  4538. assert axes >= 0, (
  4539. "The 'axes' in "
  4540. + op_type
  4541. + f" should not be negative, but received axes={axes}."
  4542. )
  4543. axes_x = range(x.ndim - axes, x.ndim)
  4544. axes_y = range(axes)
  4545. else:
  4546. if isinstance(axes, Variable):
  4547. axes = _var_to_list(axes)
  4548. if not axes or np.issubdtype(type(axes[0]), np.integer):
  4549. axes_x = axes
  4550. else:
  4551. axes_x = axes[0]
  4552. if len(axes) > 1:
  4553. axes_y = axes[1]
  4554. if isinstance(axes_x, Variable):
  4555. axes_x = _var_to_list(axes_x)
  4556. if isinstance(axes_y, Variable):
  4557. axes_y = _var_to_list(axes_y)
  4558. axes_x, axes_y = list(axes_x), list(axes_y)
  4559. len_axes_x, len_axes_y = len(axes_x), len(axes_y)
  4560. if len_axes_x < len_axes_y:
  4561. axes_x.extend(axes_y[len_axes_x:])
  4562. elif len_axes_y < len_axes_x:
  4563. axes_y.extend(axes_x[len_axes_y:])
  4564. shape_x, shape_y = list(x.shape), list(y.shape)
  4565. need_contracted_dim_x = np.zeros((x.ndim), dtype=bool)
  4566. need_contracted_dim_y = np.zeros((y.ndim), dtype=bool)
  4567. contraction_size = 1
  4568. for i in range(len(axes_x)):
  4569. dim_x, dim_y = axes_x[i], axes_y[i]
  4570. sx, sy = shape_x[dim_x], shape_y[dim_y]
  4571. if sx == 1:
  4572. shape_y[dim_y] = 1
  4573. y = y.sum(dim_y).reshape(shape_y)
  4574. elif sy == 1:
  4575. shape_x[dim_x] = 1
  4576. x = x.sum(dim_x).reshape(shape_x)
  4577. else:
  4578. assert sx == sy, (
  4579. "The dimensional size for 'x' and 'y' in "
  4580. + op_type
  4581. + f" should match each other, but 'x' has size {sx} in dim {dim_x} while 'y' has size {sy} in dim {dim_y}."
  4582. )
  4583. need_contracted_dim_x[dim_x] = True
  4584. need_contracted_dim_y[dim_y] = True
  4585. contraction_size *= shape_x[dim_x]
  4586. perm_x = []
  4587. perm_y = []
  4588. shape_out = []
  4589. not_contraction_size_x = 1
  4590. not_contraction_size_y = 1
  4591. for i in range(x.ndim):
  4592. if not need_contracted_dim_x[i]:
  4593. perm_x.append(i)
  4594. shape_out.append(shape_x[i])
  4595. not_contraction_size_x *= shape_x[i]
  4596. perm_x.extend(axes_x)
  4597. perm_y.extend(axes_y)
  4598. for i in range(y.ndim):
  4599. if not need_contracted_dim_y[i]:
  4600. perm_y.append(i)
  4601. shape_out.append(shape_y[i])
  4602. not_contraction_size_y *= shape_y[i]
  4603. x = x.transpose(perm=perm_x).reshape(
  4604. [not_contraction_size_x, contraction_size]
  4605. )
  4606. y = y.transpose(perm=perm_y).reshape(
  4607. [contraction_size, not_contraction_size_y]
  4608. )
  4609. out = x.matmul(y).reshape(shape_out)
  4610. return out
  4611. def as_complex(x, name=None):
  4612. """Transform a real tensor to a complex tensor.
  4613. The data type of the input tensor is 'float32' or 'float64', and the data
  4614. type of the returned tensor is 'complex64' or 'complex128', respectively.
  4615. The shape of the input tensor is ``(* ,2)``, (``*`` means arbitrary shape), i.e.
  4616. the size of the last axis should be 2, which represent the real and imag part
  4617. of a complex number. The shape of the returned tensor is ``(*,)``.
  4618. Args:
  4619. x (Tensor): The input tensor. Data type is 'float32' or 'float64'.
  4620. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  4621. Returns:
  4622. Tensor, The output. Data type is 'complex64' or 'complex128', with the same precision as the input.
  4623. Examples:
  4624. .. code-block:: python
  4625. >>> import paddle
  4626. >>> x = paddle.arange(12, dtype=paddle.float32).reshape([2, 3, 2])
  4627. >>> y = paddle.as_complex(x)
  4628. >>> print(y)
  4629. Tensor(shape=[2, 3], dtype=complex64, place=Place(cpu), stop_gradient=True,
  4630. [[1j , (2+3j) , (4+5j) ],
  4631. [(6+7j) , (8+9j) , (10+11j)]])
  4632. """
  4633. if in_dynamic_or_pir_mode():
  4634. return _C_ops.as_complex(x)
  4635. else:
  4636. check_variable_and_dtype(x, 'x', ['float32', 'float64'], 'as_complex')
  4637. op_type = "as_complex"
  4638. helper = LayerHelper(op_type, **locals())
  4639. inputs = {"X": x}
  4640. out = helper.create_variable_for_type_inference(
  4641. dtype=_real_to_complex_dtype(x.dtype)
  4642. )
  4643. outputs = {"Out": out}
  4644. attrs = {}
  4645. helper.append_op(
  4646. type=op_type, inputs=inputs, attrs=attrs, outputs=outputs
  4647. )
  4648. return out
  4649. def as_real(x, name=None):
  4650. """Transform a complex tensor to a real tensor.
  4651. The data type of the input tensor is 'complex64' or 'complex128', and the data
  4652. type of the returned tensor is 'float32' or 'float64', respectively.
  4653. When the shape of the input tensor is ``(*, )``, (``*`` means arbitrary shape),
  4654. the shape of the output tensor is ``(*, 2)``, i.e. the shape of the output is
  4655. the shape of the input appended by an extra ``2``.
  4656. Args:
  4657. x (Tensor): The input tensor. Data type is 'complex64' or 'complex128'.
  4658. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  4659. Returns:
  4660. Tensor, The output. Data type is 'float32' or 'float64', with the same precision as the input.
  4661. Examples:
  4662. .. code-block:: python
  4663. >>> import paddle
  4664. >>> x = paddle.arange(12, dtype=paddle.float32).reshape([2, 3, 2])
  4665. >>> y = paddle.as_complex(x)
  4666. >>> z = paddle.as_real(y)
  4667. >>> print(z)
  4668. Tensor(shape=[2, 3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
  4669. [[[0. , 1. ],
  4670. [2. , 3. ],
  4671. [4. , 5. ]],
  4672. [[6. , 7. ],
  4673. [8. , 9. ],
  4674. [10., 11.]]])
  4675. """
  4676. if in_dynamic_or_pir_mode():
  4677. return _C_ops.as_real(x)
  4678. else:
  4679. check_variable_and_dtype(x, 'x', ['complex64', 'complex128'], 'as_real')
  4680. op_type = "as_real"
  4681. helper = LayerHelper(op_type, **locals())
  4682. inputs = {"X": x}
  4683. out = helper.create_variable_for_type_inference(
  4684. dtype=_complex_to_real_dtype(x.dtype)
  4685. )
  4686. outputs = {"Out": out}
  4687. helper.append_op(type=op_type, inputs=inputs, outputs=outputs)
  4688. return out
  4689. def repeat_interleave(x, repeats, axis=None, name=None):
  4690. """
  4691. Returns a new tensor which repeats the ``x`` tensor along dimension ``axis`` using
  4692. the entries in ``repeats`` which is a int or a Tensor.
  4693. Args:
  4694. x (Tensor): The input Tensor to be operated. The data of ``x`` can be one of float32, float64, int32, int64.
  4695. repeats (Tensor or int): The number of repetitions for each element. repeats is broadcasted to fit the shape of the given axis.
  4696. axis (int, optional): The dimension in which we manipulate. Default: None, the output tensor is flatten.
  4697. name(str, optional): The default value is None. Normally there is no
  4698. need for user to set this property. For more information, please
  4699. refer to :ref:`api_guide_Name`.
  4700. Returns:
  4701. Tensor, A Tensor with same data type as ``x``.
  4702. Examples:
  4703. .. code-block:: python
  4704. >>> import paddle
  4705. >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6]])
  4706. >>> repeats = paddle.to_tensor([3, 2, 1], dtype='int32')
  4707. >>> out = paddle.repeat_interleave(x, repeats, 1)
  4708. >>> print(out)
  4709. Tensor(shape=[2, 6], dtype=int64, place=Place(cpu), stop_gradient=True,
  4710. [[1, 1, 1, 2, 2, 3],
  4711. [4, 4, 4, 5, 5, 6]])
  4712. >>> out = paddle.repeat_interleave(x, 2, 0)
  4713. >>> print(out)
  4714. Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  4715. [[1, 2, 3],
  4716. [1, 2, 3],
  4717. [4, 5, 6],
  4718. [4, 5, 6]])
  4719. >>> out = paddle.repeat_interleave(x, 2, None)
  4720. >>> print(out)
  4721. Tensor(shape=[12], dtype=int64, place=Place(cpu), stop_gradient=True,
  4722. [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6])
  4723. """
  4724. if isinstance(repeats, (Variable, paddle.pir.Value)) and not repeats.shape:
  4725. repeats = paddle.reshape(repeats, [1])
  4726. if axis is None:
  4727. x = paddle.flatten(x)
  4728. axis = 0
  4729. if in_dynamic_or_pir_mode():
  4730. if isinstance(repeats, (Variable, paddle.pir.Value)):
  4731. return _C_ops.repeat_interleave_with_tensor_index(x, repeats, axis)
  4732. return _C_ops.repeat_interleave(x, repeats, axis)
  4733. helper = LayerHelper("repeat_interleave", **locals())
  4734. check_variable_and_dtype(
  4735. x,
  4736. 'x',
  4737. ['float32', 'float64', 'int32', 'int64'],
  4738. 'paddle.tensor.manipulation.repeat_interleave',
  4739. )
  4740. out = helper.create_variable_for_type_inference(x.dtype)
  4741. helper.append_op(
  4742. type='repeat_interleave',
  4743. inputs={
  4744. 'X': x,
  4745. 'RepeatsTensor': repeats if isinstance(repeats, Variable) else None,
  4746. },
  4747. outputs={'Out': out},
  4748. attrs={
  4749. 'dim': axis,
  4750. 'Repeats': repeats if isinstance(repeats, int) else 0,
  4751. },
  4752. )
  4753. return out
  4754. def moveaxis(x, source, destination, name=None):
  4755. """
  4756. Move the axis of tensor from ``source`` position to ``destination`` position.
  4757. Other axis that have not been moved remain their original order.
  4758. Args:
  4759. x (Tensor): The input Tensor. It is a N-D Tensor of data types bool, int32, int64, float32, float64, complex64, complex128.
  4760. source(int|tuple|list): ``source`` position of axis that will be moved. Each element must be unique and integer.
  4761. destination(int|tuple|list(int)): ``destination`` position of axis that has been moved. Each element must be unique and integer.
  4762. name(str, optional): The default value is None. Normally there is no need for user to set this
  4763. property. For more information, please refer to :ref:`api_guide_Name`.
  4764. Returns:
  4765. Tensor, A new tensor whose axis have been moved.
  4766. Examples:
  4767. .. code-block:: python
  4768. >>> import paddle
  4769. >>> x = paddle.ones([3, 2, 4])
  4770. >>> outshape = paddle.moveaxis(x, [0, 1], [1, 2]).shape
  4771. >>> print(outshape)
  4772. [4, 3, 2]
  4773. >>> x = paddle.ones([2, 3])
  4774. >>> outshape = paddle.moveaxis(x, 0, 1).shape # equivalent to paddle.t(x)
  4775. >>> print(outshape)
  4776. [3, 2]
  4777. """
  4778. src = [source] if isinstance(source, int) else source
  4779. dst = [destination] if isinstance(destination, int) else destination
  4780. assert len(src) == len(
  4781. dst
  4782. ), "'source' must have the same number with 'destination'"
  4783. if len(src) != len(set(src)):
  4784. raise ValueError("Each element of 'source' must be unique!")
  4785. if len(dst) != len(set(dst)):
  4786. raise ValueError("Each element of 'destination' must be unique!")
  4787. ndim = len(x.shape)
  4788. # perm is the new order after move axis
  4789. perm = list(range(ndim))
  4790. src_dims = list(range(ndim))
  4791. dst_dims = list(range(ndim))
  4792. for i, axis in enumerate(zip(src, dst)):
  4793. assert isinstance(
  4794. axis[0], int
  4795. ), "Each element of 'source' must be integer."
  4796. if axis[0] < 0:
  4797. assert (
  4798. axis[0] >= -ndim
  4799. ), f"'source' must be in the range of [-{ndim}, {ndim})"
  4800. src[i] += ndim
  4801. else:
  4802. assert (
  4803. axis[0] < ndim
  4804. ), f"'source' must be in the range of [-{ndim}, {ndim})"
  4805. assert isinstance(
  4806. axis[1], int
  4807. ), "Each element of 'source' must be integer."
  4808. if axis[1] < 0:
  4809. assert (
  4810. axis[1] >= -ndim
  4811. ), f"'source' must be in the range of [-{ndim}, {ndim})"
  4812. dst[i] += ndim
  4813. else:
  4814. assert (
  4815. axis[1] < ndim
  4816. ), f"'source' must be in the range of [-{ndim}, {ndim})"
  4817. perm[dst[i]] = src[i]
  4818. src_dims.remove(src[i])
  4819. dst_dims.remove(dst[i])
  4820. for i in range(len(src_dims)):
  4821. perm[dst_dims[i]] = src_dims[i]
  4822. if in_dynamic_or_pir_mode():
  4823. out = _C_ops.transpose(x, perm)
  4824. return out
  4825. else:
  4826. check_variable_and_dtype(
  4827. x,
  4828. 'x',
  4829. [
  4830. 'bool',
  4831. 'float16',
  4832. 'float32',
  4833. 'float64',
  4834. 'int32',
  4835. 'int64',
  4836. 'complex64',
  4837. 'complex128',
  4838. ],
  4839. 'moveaxis',
  4840. )
  4841. helper = LayerHelper('moveaxis', **locals())
  4842. out = helper.create_variable_for_type_inference(x.dtype)
  4843. x_shape = helper.create_variable_for_type_inference(x.dtype)
  4844. helper.append_op(
  4845. type='transpose2',
  4846. inputs={'X': [x]},
  4847. outputs={'Out': [out], 'XShape': [x_shape]},
  4848. attrs={'axis': perm},
  4849. )
  4850. return out
  4851. def masked_fill(x, mask, value, name=None):
  4852. """
  4853. Fills elements of self tensor with value where mask is True. The shape of mask must be broadcastable with the shape of the underlying tensor.
  4854. Args:
  4855. x (Tensor) : The Destination Tensor. Supported data types are float,
  4856. double, int, int64_t,float16 and bfloat16.
  4857. mask (Tensor): The boolean tensor indicate the position to be filled.
  4858. The data type of mask must be bool.
  4859. value (Scalar or 0-D Tensor): The value used to fill the target tensor.
  4860. Supported data types are float, double, int, int64_t,float16 and bfloat16.
  4861. name(str, optional): The default value is None. Normally there is no
  4862. need for user to set this property. For more information, please
  4863. refer to :ref:`api_guide_Name`.
  4864. Returns:
  4865. Tensor, same dimension and dtype with x.
  4866. Examples:
  4867. .. code-block:: python
  4868. >>> # doctest: +REQUIRES(env:GPU)
  4869. >>> import paddle
  4870. >>> x = paddle.ones((3, 3), dtype="float32")
  4871. >>> mask = paddle.to_tensor([[True, True, False]])
  4872. >>> print(mask)
  4873. Tensor(shape=[1, 3], dtype=bool, place=Place(gpu:0), stop_gradient=True,
  4874. [[True , True , False]])
  4875. >>> out = paddle.masked_fill(x, mask, 2)
  4876. >>> print(out)
  4877. Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
  4878. [[2., 2., 1.],
  4879. [2., 2., 1.],
  4880. [2., 2., 1.]])
  4881. """
  4882. if np.isscalar(value):
  4883. value = paddle.full([], value, x.dtype)
  4884. mask = paddle.logical_not(mask)
  4885. out = paddle.where(mask, x, value)
  4886. return out
  4887. @inplace_apis_in_dygraph_only
  4888. def masked_fill_(x, mask, value, name=None):
  4889. """
  4890. Inplace version of ``masked_fill`` API, the output Tensor will be inplaced with input ``x``.
  4891. Please refer to :ref:`api_paddle_masked_fill`.
  4892. Examples:
  4893. .. code-block:: python
  4894. >>> # doctest: +REQUIRES(env:GPU)
  4895. >>> import paddle
  4896. >>> x = paddle.ones((3, 3), dtype="float32")
  4897. >>> mask = paddle.to_tensor([[True, False, False]])
  4898. >>> out = paddle.masked_fill_(x, mask, 2)
  4899. >>> print(out)
  4900. Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
  4901. [[2., 1., 1.],
  4902. [2., 1., 1.],
  4903. [2., 1., 1.]])
  4904. """
  4905. if np.isscalar(value):
  4906. value = paddle.full([], value, x.dtype)
  4907. mask = paddle.logical_not(mask)
  4908. out = paddle.where_(mask, x, value)
  4909. return out
  4910. def non_negative_axis(arr, axis):
  4911. ndim = len(arr.shape)
  4912. if axis >= 0:
  4913. assert axis < ndim, f"'axis' must be in the range of [-{ndim}, {ndim})"
  4914. else:
  4915. assert (
  4916. axis >= -ndim
  4917. ), f"'axis' must be in the range of [-{ndim}, {ndim})"
  4918. axis += ndim
  4919. return axis
  4920. def infer_broadcast_shape(arr, indices, axis):
  4921. # This function is used in take/put_along_axis
  4922. broadcast_shape_list = list(arr.shape)
  4923. broadcast_shape_list[axis] = list(indices.shape)[axis]
  4924. broadcast_shape = tuple(broadcast_shape_list)
  4925. for i in range(len(arr.shape)):
  4926. if arr.shape[i] < indices.shape[i]:
  4927. # if indices matrix has larger size than arr matrix, do not broadcast.
  4928. return None
  4929. return broadcast_shape
  4930. def take_along_axis(arr, indices, axis, broadcast=True):
  4931. """
  4932. Take values from the input array by given indices matrix along the designated axis.
  4933. Args:
  4934. arr (Tensor) : The input Tensor. Supported data types are float32 and float64.
  4935. indices (Tensor) : Indices to take along each 1d slice of arr. This must match the dimension of arr,
  4936. and need to broadcast against arr. Supported data type are int and int64.
  4937. axis (int) : The axis to take 1d slices along.
  4938. broadcast (bool, optional): whether the indices broadcast.
  4939. Returns:
  4940. Tensor, The indexed element, same dtype with arr
  4941. Examples:
  4942. .. code-block:: python
  4943. >>> import paddle
  4944. >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7,8,9]])
  4945. >>> index = paddle.to_tensor([[0]])
  4946. >>> axis = 0
  4947. >>> result = paddle.take_along_axis(x, index, axis)
  4948. >>> print(result)
  4949. Tensor(shape=[1, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  4950. [[1, 2, 3]])
  4951. """
  4952. if len(arr.shape) != len(indices.shape):
  4953. raise ValueError(
  4954. "`indices` and `arr` must have the same number of dimensions!"
  4955. )
  4956. axis = non_negative_axis(arr, axis)
  4957. if broadcast:
  4958. broadcast_shape = infer_broadcast_shape(arr, indices, axis)
  4959. if not broadcast_shape:
  4960. # if indices matrix have larger size than arr, arr should broadcast into indices shape.
  4961. broadcast_shape = indices.shape
  4962. indices = paddle.broadcast_to(indices, broadcast_shape)
  4963. broadcast_shape_list = list(broadcast_shape)
  4964. broadcast_shape_list[axis] = list(arr.shape)[axis]
  4965. broadcast_shape = tuple(broadcast_shape_list)
  4966. arr = paddle.broadcast_to(arr, broadcast_shape)
  4967. else:
  4968. for i in range(len(arr.shape)):
  4969. if i != axis and arr.shape[i] < indices.shape[i]:
  4970. raise RuntimeError(
  4971. f"Size does not match at dimension {i} expected index {indices.shape} to be smaller than self {arr.shape} apart from dimension {axis}"
  4972. )
  4973. axis_max_size = arr.shape[axis]
  4974. if in_dynamic_mode() and not (indices < axis_max_size).all():
  4975. raise RuntimeError(
  4976. f"one of element of indices is out of bounds for dimension {axis} with size {axis_max_size}"
  4977. )
  4978. if in_dynamic_or_pir_mode():
  4979. return _C_ops.take_along_axis(arr, indices, axis)
  4980. else:
  4981. check_variable_and_dtype(
  4982. arr,
  4983. 'x',
  4984. [
  4985. 'float16',
  4986. 'float32',
  4987. 'float64',
  4988. 'int32',
  4989. 'int64',
  4990. 'uint8',
  4991. 'uint16',
  4992. ],
  4993. 'take_along_axis',
  4994. )
  4995. check_variable_and_dtype(
  4996. indices, 'index', ['int32', 'int64'], 'take_along_axis'
  4997. )
  4998. helper = LayerHelper('take_along_axis', **locals())
  4999. dtype = helper.input_dtype()
  5000. result = helper.create_variable_for_type_inference(dtype)
  5001. helper.append_op(
  5002. type="take_along_axis",
  5003. inputs={"Input": arr, "Index": indices},
  5004. attrs={"Axis": axis},
  5005. outputs={"Result": result},
  5006. )
  5007. return result
  5008. def put_along_axis(
  5009. arr,
  5010. indices,
  5011. values,
  5012. axis,
  5013. reduce='assign',
  5014. include_self=True,
  5015. broadcast=True,
  5016. ):
  5017. """
  5018. Put values into the destination array by given indices matrix along the designated axis.
  5019. Args:
  5020. arr (Tensor) : The Destination Tensor. Supported data types are float32 and float64.
  5021. indices (Tensor) : Indices to put along each 1d slice of arr. This must match the dimension of arr,
  5022. and need to broadcast against arr if broadcast is 'True'. Supported data type are int and int64.
  5023. values (Tensor) : The value element(s) to put. The data types should be same as arr.
  5024. axis (int) : The axis to put 1d slices along.
  5025. reduce (str, optional): The reduce operation, default is 'assign', support 'add', 'assign', 'mul', 'multiply', 'mean', 'amin' and 'amax'.
  5026. include_self (bool, optional): whether to reduce with the elements of arr, default is 'True'.
  5027. broadcast (bool, optional): whether to broadcast indices, default is 'True'.
  5028. Returns:
  5029. Tensor, The indexed element, same dtype with arr
  5030. Examples:
  5031. .. code-block:: python
  5032. >>> import paddle
  5033. >>> x = paddle.to_tensor([[10, 30, 20], [60, 40, 50]])
  5034. >>> index = paddle.to_tensor([[0]])
  5035. >>> value = 99
  5036. >>> axis = 0
  5037. >>> result = paddle.put_along_axis(x, index, value, axis)
  5038. >>> print(result)
  5039. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5040. [[99, 99, 99],
  5041. [60, 40, 50]])
  5042. >>> index = paddle.zeros((2,2)).astype("int32")
  5043. >>> value=paddle.to_tensor([[1,2],[3,4]]).astype(x.dtype)
  5044. >>> result = paddle.put_along_axis(x, index, value, 0, "add", True, False)
  5045. >>> print(result)
  5046. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5047. [[14, 36, 20],
  5048. [60, 40, 50]])
  5049. >>> result = paddle.put_along_axis(x, index, value, 0, "mul", True, False)
  5050. >>> print(result)
  5051. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5052. [[30 , 240, 20 ],
  5053. [60 , 40 , 50 ]])
  5054. >>> result = paddle.put_along_axis(x, index, value, 0, "mean", True, False)
  5055. >>> print(result)
  5056. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5057. [[4 , 12, 20],
  5058. [60, 40, 50]])
  5059. >>> result = paddle.put_along_axis(x, index, value, 0, "amin", True, False)
  5060. >>> print(result)
  5061. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5062. [[1 , 2 , 20],
  5063. [60, 40, 50]])
  5064. >>> result = paddle.put_along_axis(x, index, value, 0, "amax", True, False)
  5065. >>> print(result)
  5066. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5067. [[10, 30, 20],
  5068. [60, 40, 50]])
  5069. >>> result = paddle.put_along_axis(x, index, value, 0, "add", False, False)
  5070. >>> print(result)
  5071. Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
  5072. [[4 , 6 , 20],
  5073. [60, 40, 50]])
  5074. """
  5075. if len(arr.shape) != len(indices.shape):
  5076. raise ValueError(
  5077. "`indices` and `arr` must have the same number of dimensions!"
  5078. )
  5079. axis = non_negative_axis(arr, axis)
  5080. if broadcast:
  5081. broadcast_shape = infer_broadcast_shape(arr, indices, axis)
  5082. if in_dynamic_or_pir_mode():
  5083. values = (
  5084. paddle.to_tensor(values)
  5085. if not isinstance(values, (paddle.Tensor, paddle.pir.Value))
  5086. else values
  5087. )
  5088. if broadcast_shape:
  5089. indices = paddle.broadcast_to(indices, broadcast_shape)
  5090. values = paddle.broadcast_to(values, indices.shape)
  5091. else:
  5092. if isinstance(values, (paddle.Tensor, paddle.pir.Value)):
  5093. if len(indices.shape) != len(values.shape):
  5094. raise ValueError(
  5095. "`indices` and `values` must have the same number of dimensions!"
  5096. )
  5097. for i in range(len(arr.shape)):
  5098. if (
  5099. i != axis and arr.shape[i] < indices.shape[i]
  5100. ) or indices.shape[i] > values.shape[i]:
  5101. raise RuntimeError(
  5102. f"Size does not match at dimension {i} expected index {indices.shape} to be smaller than self {arr.shape} apart from dimension {axis} and to be smaller size than values {values.shape}"
  5103. )
  5104. else:
  5105. values = paddle.to_tensor(values).astype(arr.dtype)
  5106. elements = 1
  5107. for num in values.shape:
  5108. elements *= num
  5109. if elements == 1: # paddle.pir.Value has no attribute 'size'
  5110. values = paddle.broadcast_to(values, indices.shape)
  5111. axis_max_size = arr.shape[axis]
  5112. if in_dynamic_mode() and not (indices < axis_max_size).all():
  5113. raise RuntimeError(
  5114. f"one of element of indices is out of bounds for dimension {axis} with size {axis_max_size}"
  5115. )
  5116. if in_dynamic_or_pir_mode():
  5117. if convert_dtype(indices.dtype) not in ['int32', 'int64']:
  5118. raise TypeError(
  5119. f"The data type of indices should be one of ['int32', 'int64'], but got {str(convert_dtype(indices.dtype))}"
  5120. )
  5121. return _C_ops.put_along_axis(
  5122. arr, indices, values, axis, reduce, include_self
  5123. )
  5124. else:
  5125. check_variable_and_dtype(
  5126. arr,
  5127. 'x',
  5128. [
  5129. 'float16',
  5130. 'float32',
  5131. 'float64',
  5132. 'int32',
  5133. 'int64',
  5134. 'uint8',
  5135. 'uint16',
  5136. ],
  5137. 'put_along_axis',
  5138. )
  5139. check_variable_and_dtype(
  5140. indices, 'index', ['int32', 'int64'], 'put_along_axis'
  5141. )
  5142. check_type(include_self, 'include_self', bool, 'put_along_axis')
  5143. helper = LayerHelper('put_along_axis', **locals())
  5144. dtype = helper.input_dtype()
  5145. result = helper.create_variable_for_type_inference(dtype)
  5146. helper.append_op(
  5147. type="put_along_axis",
  5148. inputs={"Input": arr, "Index": indices, "Value": values},
  5149. attrs={
  5150. "Axis": axis,
  5151. "Reduce": reduce,
  5152. "Include_self": include_self,
  5153. },
  5154. outputs={"Result": result},
  5155. )
  5156. return result
  5157. @inplace_apis_in_dygraph_only
  5158. def put_along_axis_(
  5159. arr, indices, values, axis, reduce='assign', include_self=True
  5160. ):
  5161. r"""
  5162. Inplace version of ``put_along_axis`` API, the output Tensor will be inplaced with input ``arr``.
  5163. Please refer to :ref:`api_paddle_put_along_axis`.
  5164. """
  5165. if len(arr.shape) != len(indices.shape):
  5166. raise ValueError(
  5167. "`indices` and `arr` must have the same number of dimensions!"
  5168. )
  5169. axis = non_negative_axis(arr, axis)
  5170. broadcast_shape = infer_broadcast_shape(arr, indices, axis)
  5171. values = (
  5172. paddle.to_tensor(values)
  5173. if not isinstance(values, paddle.Tensor)
  5174. else values
  5175. )
  5176. if broadcast_shape:
  5177. indices = paddle.broadcast_to(indices, broadcast_shape)
  5178. values = paddle.broadcast_to(values, indices.shape)
  5179. return _C_ops.put_along_axis_(
  5180. arr, indices, values, axis, reduce, include_self
  5181. )
  5182. def index_add(x, index, axis, value, name=None):
  5183. """
  5184. Adds the elements of the input tensor with value tensor by selecting the indices in the order given in index.
  5185. Args:
  5186. x (Tensor) : The Destination Tensor. Supported data types are int32, int64, float16, float32, float64.
  5187. index (Tensor): The 1-D Tensor containing the indices to index.
  5188. The data type of ``index`` must be int32 or int64.
  5189. axis (int): The dimension in which we index.
  5190. value (Tensor): The tensor used to add the elements along the target axis.
  5191. name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
  5192. Returns:
  5193. Tensor, same dimension and dtype with x.
  5194. Examples:
  5195. .. code-block:: python
  5196. >>> # doctest: +REQUIRES(env:GPU)
  5197. >>> import paddle
  5198. >>> paddle.device.set_device('gpu')
  5199. >>> input_tensor = paddle.to_tensor(paddle.ones((3, 3)), dtype="float32")
  5200. >>> index = paddle.to_tensor([0, 2], dtype="int32")
  5201. >>> value = paddle.to_tensor([[1, 1, 1], [1, 1, 1]], dtype="float32")
  5202. >>> outplace_res = paddle.index_add(input_tensor, index, 0, value)
  5203. >>> print(outplace_res)
  5204. Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
  5205. [[2., 2., 2.],
  5206. [1., 1., 1.],
  5207. [2., 2., 2.]])
  5208. """
  5209. if in_dynamic_or_pir_mode():
  5210. return _C_ops.index_add(x, index, value, axis)
  5211. helper = LayerHelper("index_add", **locals())
  5212. check_variable_and_dtype(
  5213. x,
  5214. 'x',
  5215. ['float16', 'float32', 'float64', 'int32', 'int64', 'uint16'],
  5216. 'paddle.tensor.manipulation.index_add',
  5217. )
  5218. check_variable_and_dtype(
  5219. index,
  5220. 'index',
  5221. ['int32', 'int64'],
  5222. 'paddle.tensor.manipulation.index_add',
  5223. )
  5224. check_variable_and_dtype(
  5225. value,
  5226. 'add_value',
  5227. ['float16', 'float32', 'float64', 'int32', 'int64', 'uint16'],
  5228. 'paddle.tensor.manipulation.index_add',
  5229. )
  5230. out = helper.create_variable_for_type_inference(x.dtype)
  5231. helper.append_op(
  5232. type='index_add',
  5233. inputs={
  5234. 'X': x,
  5235. 'Index': index,
  5236. 'AddValue': value,
  5237. },
  5238. outputs={'Out': out},
  5239. attrs={'axis': axis},
  5240. )
  5241. return out
  5242. @inplace_apis_in_dygraph_only
  5243. def index_add_(x, index, axis, value, name=None):
  5244. """
  5245. Inplace version of ``index_add`` API, the output Tensor will be inplaced with input ``x``.
  5246. Please refer to :ref:`api_paddle_index_add`.
  5247. Examples:
  5248. .. code-block:: python
  5249. >>> # doctest: +REQUIRES(env:GPU)
  5250. >>> import paddle
  5251. >>> paddle.device.set_device('gpu')
  5252. >>> input_tensor = paddle.to_tensor(paddle.ones((3, 3)), dtype="float32")
  5253. >>> index = paddle.to_tensor([0, 2], dtype="int32")
  5254. >>> value = paddle.to_tensor([[1, 1], [1, 1], [1, 1]], dtype="float32")
  5255. >>> inplace_res = paddle.index_add_(input_tensor, index, 1, value)
  5256. >>> print(inplace_res)
  5257. Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
  5258. [[2., 1., 2.],
  5259. [2., 1., 2.],
  5260. [2., 1., 2.]])
  5261. """
  5262. return _C_ops.index_add_(x, index, value, axis)
  5263. @inplace_apis_in_dygraph_only
  5264. def index_put_(x, indices, value, accumulate=False, name=None):
  5265. """
  5266. Puts values from the tensor values into the tensor x using the indices specified in indices (which is a tuple of Tensors).
  5267. The expression paddle.index_put_(x, indices, values) is equivalent to tensor[indices] = values. Returns x.
  5268. If accumulate is True, the elements in values are added to x. If accumulate is False, the behavior is undefined if indices contain duplicate elements.
  5269. Args:
  5270. x (Tensor) : The Source Tensor. Supported data types are int32, int64, float16, float32, float64, bool.
  5271. indices (Tuple of Tensor): The tuple of Tensor containing the indices to index.
  5272. The data type of ``tensor in indices`` must be int32, int64 or bool.
  5273. value (Tensor): The tensor used to be assigned to x.
  5274. accumulate (Bool, optional): Whether the elements in values are added to x. Default: False.
  5275. name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
  5276. Returns:
  5277. Tensor, same dimension and dtype with x.
  5278. Examples:
  5279. .. code-block:: python
  5280. >>> import paddle
  5281. >>> x = paddle.zeros([3, 3])
  5282. >>> value = paddle.ones([3])
  5283. >>> ix1 = paddle.to_tensor([0,1,2])
  5284. >>> ix2 = paddle.to_tensor([1,2,1])
  5285. >>> indices=(ix1,ix2)
  5286. >>> out = paddle.index_put_(x,indices,value)
  5287. >>> print(x)
  5288. Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  5289. [[0., 1., 0.],
  5290. [0., 0., 1.],
  5291. [0., 1., 0.]])
  5292. >>> print(out)
  5293. Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  5294. [[0., 1., 0.],
  5295. [0., 0., 1.],
  5296. [0., 1., 0.]])
  5297. """
  5298. return _C_ops.index_put_(x, indices, value, accumulate)
  5299. def index_put(x, indices, value, accumulate=False, name=None):
  5300. """
  5301. Outplace version of ``index_put_`` API, the output Tensor will be inplaced with input ``x``.
  5302. Please refer to :ref:`api_paddle_index_put`.
  5303. Examples:
  5304. .. code-block:: python
  5305. >>> import paddle
  5306. >>> x = paddle.zeros([3, 3])
  5307. >>> value = paddle.ones([3])
  5308. >>> ix1 = paddle.to_tensor([0,1,2])
  5309. >>> ix2 = paddle.to_tensor([1,2,1])
  5310. >>> indices=(ix1,ix2)
  5311. >>> out = paddle.index_put(x,indices,value)
  5312. >>> print(x)
  5313. Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  5314. [[0., 0., 0.],
  5315. [0., 0., 0.],
  5316. [0., 0., 0.]])
  5317. >>> print(out)
  5318. Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
  5319. [[0., 1., 0.],
  5320. [0., 0., 1.],
  5321. [0., 1., 0.]])
  5322. """
  5323. if in_dynamic_or_pir_mode():
  5324. return _C_ops.index_put(x, indices, value, accumulate)
  5325. helper = LayerHelper("index_put", **locals())
  5326. check_variable_and_dtype(
  5327. x,
  5328. 'x',
  5329. ['float16', 'float32', 'float64', 'int32', 'int64', 'bool'],
  5330. 'paddle.tensor.manipulation.index_put',
  5331. )
  5332. check_variable_and_dtype(
  5333. value,
  5334. 'value',
  5335. ['float16', 'float32', 'float64', 'int32', 'int64', 'bool'],
  5336. 'paddle.tensor.manipulation.index_put',
  5337. )
  5338. out = helper.create_variable_for_type_inference(x.dtype)
  5339. helper.append_op(
  5340. type='index_put',
  5341. inputs={
  5342. 'x': x,
  5343. 'indices': indices,
  5344. 'value': value,
  5345. },
  5346. outputs={'out': out},
  5347. attrs={'accumulate': accumulate},
  5348. )
  5349. return out
  5350. def unflatten(x, axis, shape, name=None):
  5351. """
  5352. Expand a certain dimension of the input x Tensor into a desired shape.
  5353. Args:
  5354. x (Tensor) : An N-D Tensor. The data type is float16, float32, float64, int16, int32, int64, bool, uint16.
  5355. axis (int): :attr:`axis` to be unflattened, specified as an index into `x.shape`.
  5356. shape (list|tuple|Tensor): Unflatten :attr:`shape` on the specified :attr:`axis`. At most one dimension of the target :attr:`shape` can be -1.
  5357. If the input :attr:`shape` does not contain -1 , the product of all elements in ``shape`` should be equal to ``x.shape[axis]``.
  5358. The data type is `int` . If :attr:`shape` is a list or tuple, the elements of it should be integers or Tensors with shape [].
  5359. If :attr:`shape` is an Tensor, it should be an 1-D Tensor.
  5360. name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
  5361. Returns:
  5362. Tensor, return the unflatten tensor of :attr:`x`.
  5363. Examples:
  5364. .. code-block:: python
  5365. >>> import paddle
  5366. >>> x = paddle.randn(shape=[4, 6, 8])
  5367. >>> shape = [2, 3]
  5368. >>> axis = 1
  5369. >>> res = paddle.unflatten(x, axis, shape)
  5370. >>> print(res.shape)
  5371. [4, 2, 3, 8]
  5372. >>> x = paddle.randn(shape=[4, 6, 8])
  5373. >>> shape = (-1, 2)
  5374. >>> axis = -1
  5375. >>> res = paddle.unflatten(x, axis, shape)
  5376. >>> print(res.shape)
  5377. [4, 6, 4, 2]
  5378. >>> x = paddle.randn(shape=[4, 6, 8])
  5379. >>> shape = paddle.to_tensor([2, 2])
  5380. >>> axis = 0
  5381. >>> res = paddle.unflatten(x, axis, shape)
  5382. >>> print(res.shape)
  5383. [2, 2, 6, 8]
  5384. """
  5385. # determine whether the input axis is valid.
  5386. axis = non_negative_axis(x, axis)
  5387. if isinstance(shape, (list, tuple)):
  5388. new_shape = (
  5389. list(x.shape[:axis]) + list(shape) + list(x.shape[axis + 1 :])
  5390. )
  5391. elif isinstance(shape, (Variable, paddle.pir.Value)):
  5392. # The data type returned by `paddle.shape` is only 'int32'.
  5393. new_shape = paddle.concat(
  5394. [
  5395. paddle.shape(x)[:axis],
  5396. paddle.cast(shape, 'int32'),
  5397. paddle.shape(x)[axis + 1 :],
  5398. ]
  5399. )
  5400. else:
  5401. raise TypeError(
  5402. f"The data type of x should be one of ['List', 'Tuple', 'Tensor'], but got {type(shape)}"
  5403. )
  5404. x = x.reshape(new_shape)
  5405. return x
  5406. @dygraph_only
  5407. def as_strided(x, shape, stride, offset=0, name=None):
  5408. """
  5409. View x with specified shape, stride and offset.
  5410. Note that the output Tensor will share data with origin Tensor and doesn't
  5411. have a Tensor copy in ``dygraph`` mode.
  5412. Args:
  5413. x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
  5414. shape (list|tuple): Define the target shape. Each element of it should be integer.
  5415. stride (list|tuple): Define the target stride. Each element of it should be integer.
  5416. offset (int): Define the target Tensor's offset from x's holder. Default: 0.
  5417. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  5418. Returns:
  5419. Tensor, A as_strided Tensor with the same data type as ``x``.
  5420. Examples:
  5421. .. code-block:: python
  5422. >>> import paddle
  5423. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5424. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5425. >>> out = paddle.as_strided(x, [8, 6], [6, 1])
  5426. >>> print(out.shape)
  5427. [8, 6]
  5428. >>> # the stride is [6, 1].
  5429. """
  5430. return _C_ops.as_strided(x, shape, stride, offset)
  5431. @dygraph_only
  5432. def view(x, shape_or_dtype, name=None):
  5433. """
  5434. View x with specified shape or dtype.
  5435. Note that the output Tensor will share data with origin Tensor and doesn't
  5436. have a Tensor copy in ``dygraph`` mode.
  5437. Args:
  5438. x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
  5439. shape_or_dtype (list|tuple|np.dtype|str|VarType): Define the target shape or dtype. If list or tuple, shape_or_dtype represents shape, each element of it should be integer. If np.dtype or str or VarType, shape_or_dtype represents dtype, it can be bool, float16, float32, float64, int8, int32, int64, uint8.
  5440. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  5441. Returns:
  5442. Tensor, A viewed Tensor with the same data as ``x``.
  5443. Examples:
  5444. .. code-block:: python
  5445. >>> import paddle
  5446. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5447. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5448. >>> out = paddle.view(x, [8, 6])
  5449. >>> print(out.shape)
  5450. [8, 6]
  5451. >>> import paddle
  5452. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5453. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5454. >>> out = paddle.view(x, "uint8")
  5455. >>> print(out.shape)
  5456. [2, 4, 24]
  5457. >>> import paddle
  5458. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5459. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5460. >>> out = paddle.view(x, [8, -1])
  5461. >>> print(out.shape)
  5462. [8, 6]
  5463. >>> import paddle
  5464. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5465. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5466. >>> out = paddle.view(x, paddle.uint8)
  5467. >>> print(out.shape)
  5468. [2, 4, 24]
  5469. """
  5470. if isinstance(shape_or_dtype, (list, tuple)):
  5471. return _C_ops.view_shape(x, shape_or_dtype)
  5472. else:
  5473. if not isinstance(shape_or_dtype, core.VarDesc.VarType):
  5474. shape_or_dtype = convert_np_dtype_to_dtype_(shape_or_dtype)
  5475. return _C_ops.view_dtype(x, shape_or_dtype)
  5476. @dygraph_only
  5477. def view_as(x, other, name=None):
  5478. """
  5479. View x with other's shape.
  5480. Note that the output Tensor will share data with origin Tensor and doesn't
  5481. have a Tensor copy in ``dygraph`` mode.
  5482. Args:
  5483. x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
  5484. other (Tensor): The result tensor has the same size as other.
  5485. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  5486. Returns:
  5487. Tensor, A viewed Tensor with the same shape as ``other``.
  5488. Examples:
  5489. .. code-block:: python
  5490. >>> import paddle
  5491. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5492. >>> x = paddle.rand([2, 4, 6], dtype="float32")
  5493. >>> y = paddle.rand([8, 6], dtype="float32")
  5494. >>> out = paddle.view_as(x, y)
  5495. >>> print(out.shape)
  5496. [8, 6]
  5497. """
  5498. return _C_ops.view_shape(x, other.shape)
  5499. @dygraph_only
  5500. def unfold(x, axis, size, step, name=None):
  5501. """
  5502. View x with specified shape, stride and offset, which contains all slices of size from x in the dimension axis.
  5503. Note that the output Tensor will share data with origin Tensor and doesn't
  5504. have a Tensor copy in ``dygraph`` mode.
  5505. Args:
  5506. x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
  5507. axis (int): The axis along which the input is unfolded.
  5508. size (int): The size of each slice that is unfolded.
  5509. step (int): The step between each slice.
  5510. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  5511. Returns:
  5512. Tensor, A unfold Tensor with the same data type as ``x``.
  5513. Examples:
  5514. .. code-block:: python
  5515. >>> import paddle
  5516. >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})
  5517. >>> x = paddle.arange(9, dtype="float64")
  5518. >>> out = paddle.unfold(x, 0, 2, 4)
  5519. >>> print(out)
  5520. Tensor(shape=[2, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
  5521. [[0., 1.],
  5522. [4., 5.]])
  5523. """
  5524. return _C_ops.tensor_unfold(x, axis, size, step)
  5525. # TODO(dev): We need avoid implementing it by this way.
  5526. __METHODS = {
  5527. 'fill_': fill_,
  5528. 'zero_': zero_,
  5529. 'fill_diagonal_': fill_diagonal_,
  5530. 'fill_diagonal_tensor_': fill_diagonal_tensor_,
  5531. "fill_diagonal_tensor": fill_diagonal_tensor,
  5532. 'tolist': tolist,
  5533. }
  5534. for name, func in __METHODS.items():
  5535. setattr(core.eager.Tensor, name, func)
  5536. def _index_fill_impl(x, index, axis, value, inplace):
  5537. if not isinstance(index, (Variable, paddle.pir.Value)):
  5538. raise ValueError("index must be Tensor")
  5539. if not isinstance(value, Variable):
  5540. value = paddle.to_tensor(value, dtype=x.dtype)
  5541. else:
  5542. if len(value.shape) > 0:
  5543. raise ValueError("value must be scalar or 0-D tensor")
  5544. x_dim = len(x.shape)
  5545. if not (isinstance(axis, int)) or (axis > x_dim - 1) or axis < -x_dim:
  5546. raise ValueError(
  5547. "The axis should be int, and in range [-rank(x), rank(x))"
  5548. )
  5549. if axis < 0:
  5550. axis = axis + x_dim
  5551. perm = list(range(len(x.shape)))
  5552. perm[0] = axis
  5553. perm[axis] = 0
  5554. if inplace:
  5555. paddle.transpose_(x, perm)
  5556. paddle.index_put_(x, (index,), value)
  5557. paddle.transpose_(x, perm)
  5558. return x
  5559. else:
  5560. out = paddle.transpose(x, perm)
  5561. out = paddle.index_put(out, (index,), value)
  5562. out = paddle.transpose(out, perm)
  5563. return out
  5564. def index_fill(x, index, axis, value, name=None):
  5565. """
  5566. Outplace version of ``index_fill_`` API, the output Tensor will be inplaced with input ``x``.
  5567. Please refer to :ref:`api_paddle_index_fill_`.
  5568. Examples:
  5569. .. code-block:: python
  5570. >>> import paddle
  5571. >>> input_tensor = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype='int64')
  5572. >>> index = paddle.to_tensor([0, 2], dtype="int32")
  5573. >>> value = -1
  5574. >>> res = paddle.index_fill(input_tensor, index, 0, value)
  5575. >>> print(input_tensor)
  5576. Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
  5577. [[1, 2, 3],
  5578. [4, 5, 6],
  5579. [7, 8, 9]])
  5580. >>> print(res)
  5581. Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
  5582. [[-1, -1, -1],
  5583. [ 4, 5, 6],
  5584. [-1, -1, -1]])
  5585. """
  5586. return _index_fill_impl(x, index, axis, value, False)
  5587. @inplace_apis_in_dygraph_only
  5588. def index_fill_(x, index, axis, value, name=None):
  5589. """
  5590. Fill the elements of the input tensor with value by the specific axis and index.
  5591. Args:
  5592. x (Tensor) : The Destination Tensor. Supported data types are int32, int64, float16, float32, float64.
  5593. index (Tensor): The 1-D Tensor containing the indices to index.
  5594. The data type of ``index`` must be int32 or int64.
  5595. axis (int): The dimension along which to index.
  5596. value (float): The tensor used to fill with.
  5597. name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
  5598. Returns:
  5599. Tensor, same dimension and dtype with x.
  5600. Examples:
  5601. .. code-block:: python
  5602. >>> import paddle
  5603. >>> input_tensor = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype='int64')
  5604. >>> index = paddle.to_tensor([0, 2], dtype="int32")
  5605. >>> value = -1
  5606. >>> res = paddle.index_fill_(input_tensor, index, 0, value)
  5607. >>> print(input_tensor)
  5608. Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
  5609. [[-1, -1, -1],
  5610. [ 4, 5, 6],
  5611. [-1, -1, -1]])
  5612. >>> print(res)
  5613. Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
  5614. [[-1, -1, -1],
  5615. [ 4, 5, 6],
  5616. [-1, -1, -1]])
  5617. """
  5618. return _index_fill_impl(x, index, axis, value, True)
  5619. def diagonal_scatter(x, y, offset=0, axis1=0, axis2=1, name=None):
  5620. """
  5621. Embed the values of Tensor ``y`` into Tensor ``x`` along the diagonal elements
  5622. of Tensor ``x``, with respect to ``axis1`` and ``axis2``.
  5623. This function returns a tensor with fresh storage.
  5624. The argument ``offset`` controls which diagonal to consider:
  5625. - If ``offset`` = 0, it is the main diagonal.
  5626. - If ``offset`` > 0, it is above the main diagonal.
  5627. - If ``offset`` < 0, it is below the main diagonal.
  5628. Note:
  5629. ``y`` should have the same shape as :ref:`paddle.diagonal <api_paddle_diagonal>`.
  5630. Args:
  5631. x (Tensor): ``x`` is the original Tensor. Must be at least 2-dimensional.
  5632. y (Tensor): ``y`` is the Tensor to embed into ``x``
  5633. offset (int, optional): which diagonal to consider. Default: 0 (main diagonal).
  5634. axis1 (int, optional): first axis with respect to which to take diagonal. Default: 0.
  5635. axis2 (int, optional): second axis with respect to which to take diagonal. Default: 1.
  5636. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  5637. Returns:
  5638. Tensor, Tensor with diagonal embedded with ``y``.
  5639. Examples:
  5640. .. code-block:: python
  5641. >>> import paddle
  5642. >>> x = paddle.arange(6.0).reshape((2, 3))
  5643. >>> y = paddle.ones((2,))
  5644. >>> out = x.diagonal_scatter(y)
  5645. >>> print(out)
  5646. Tensor(shape=[2, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
  5647. [[1., 1., 2.],
  5648. [3., 1., 5.]])
  5649. """
  5650. return fill_diagonal_tensor(x, y, offset, axis1, axis2, name)
  5651. def select_scatter(x, values, axis, index, name=None):
  5652. """
  5653. Embeds the values of the values tensor into x at the given index of axis.
  5654. Args:
  5655. x (Tensor) : The Destination Tensor. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
  5656. values (Tensor) : The tensor to embed into x. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
  5657. axis (int) : the dimension to insert the slice into.
  5658. index (int) : the index to select with.
  5659. name (str, optional): Name for the operation (optional, default is None).
  5660. Returns:
  5661. Tensor, same dtype and shape with x
  5662. Examples:
  5663. .. code-block:: python
  5664. >>> import paddle
  5665. >>> x = paddle.zeros((2,3,4)).astype("float32")
  5666. >>> values = paddle.ones((2,4)).astype("float32")
  5667. >>> res = paddle.select_scatter(x,values,1,1)
  5668. >>> print(res)
  5669. Tensor(shape=[2, 3, 4], dtype=float32, place=Place(cpu), stop_gradient=True,
  5670. [[[0., 0., 0., 0.],
  5671. [1., 1., 1., 1.],
  5672. [0., 0., 0., 0.]],
  5673. [[0., 0., 0., 0.],
  5674. [1., 1., 1., 1.],
  5675. [0., 0., 0., 0.]]])
  5676. """
  5677. x_shape = x.shape
  5678. value_shape = values.shape
  5679. if not isinstance(x_shape, list):
  5680. x_shape = list(x_shape)
  5681. if index < 0:
  5682. index += x_shape[axis]
  5683. if axis < 0:
  5684. axis += len(x_shape)
  5685. del x_shape[axis]
  5686. if len(x_shape) != len(value_shape):
  5687. raise RuntimeError(
  5688. "expected values to have a size equal to the slice of x. value size = "
  5689. + str(value_shape)
  5690. + " slice size = "
  5691. + str(x_shape)
  5692. )
  5693. for i in range(len(x_shape)):
  5694. if x_shape[i] != value_shape[i]:
  5695. raise RuntimeError(
  5696. "expected values to have a size equal to the slice of x. value size = "
  5697. + str(value_shape)
  5698. + " slice size = "
  5699. + str(x_shape)
  5700. )
  5701. from ..base.framework import default_main_program
  5702. starts = [index]
  5703. ends = [index + 1]
  5704. steps = [1]
  5705. axes = [axis]
  5706. none_axes = []
  5707. decrease_axes = [axis]
  5708. inputs = {'Input': x}
  5709. attrs = {
  5710. 'axes': axes,
  5711. 'starts': starts,
  5712. 'ends': ends,
  5713. 'steps': steps,
  5714. 'decrease_axes': decrease_axes,
  5715. 'none_axes': none_axes,
  5716. }
  5717. dtype = x.dtype
  5718. attrs['dtype'] = dtype
  5719. values = values.astype(dtype)
  5720. inputs["ValueTensor"] = values
  5721. if in_dynamic_or_pir_mode():
  5722. return _C_ops.set_value_with_tensor(
  5723. x,
  5724. values,
  5725. starts,
  5726. ends,
  5727. steps,
  5728. axes,
  5729. decrease_axes,
  5730. none_axes,
  5731. )
  5732. else:
  5733. helper = LayerHelper('select_scatter', **locals())
  5734. output = helper.create_variable_for_type_inference(dtype=x.dtype)
  5735. cur_block = default_main_program().current_block()
  5736. cur_block.append_op(
  5737. type="set_value",
  5738. inputs=inputs,
  5739. outputs={'Out': output},
  5740. attrs=attrs,
  5741. inplace_map={"Input": "Out"},
  5742. )
  5743. return output
  5744. def slice_scatter(x, value, axes, starts, ends, strides, name=None):
  5745. """
  5746. Embeds the `value` tensor into `x` along multiple axes. Returns a new tensor instead of a view.
  5747. The size of `axes` must be equal to `starts` , `ends` and `strides`.
  5748. Args:
  5749. x (Tensor) : The input Tensor. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
  5750. value (Tensor) : The tensor to embed into x. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
  5751. axes (list|tuple) : the dimensions to insert the value.
  5752. starts (list|tuple) : the start indices of where to insert.
  5753. ends (list|tuple) : the stop indices of where to insert.
  5754. strides (list|tuple) : the steps for each insert.
  5755. name (str, optional): Name for the operation (optional, default is None).
  5756. Returns:
  5757. Tensor, same dtype and shape with x
  5758. Examples:
  5759. .. code-block:: python
  5760. >>> import paddle
  5761. >>> x = paddle.zeros((3, 9))
  5762. >>> value = paddle.ones((3, 2))
  5763. >>> res = paddle.slice_scatter(x, value, axes=[1], starts=[2], ends=[6], strides=[2])
  5764. >>> print(res)
  5765. Tensor(shape=[3, 9], dtype=float32, place=Place(cpu), stop_gradient=True,
  5766. [[0., 0., 1., 0., 1., 0., 0., 0., 0.],
  5767. [0., 0., 1., 0., 1., 0., 0., 0., 0.],
  5768. [0., 0., 1., 0., 1., 0., 0., 0., 0.]])
  5769. >>> # broadcast `value` got the same result
  5770. >>> x = paddle.zeros((3, 9))
  5771. >>> value = paddle.ones((3, 1))
  5772. >>> res = paddle.slice_scatter(x, value, axes=[1], starts=[2], ends=[6], strides=[2])
  5773. >>> print(res)
  5774. Tensor(shape=[3, 9], dtype=float32, place=Place(cpu), stop_gradient=True,
  5775. [[0., 0., 1., 0., 1., 0., 0., 0., 0.],
  5776. [0., 0., 1., 0., 1., 0., 0., 0., 0.],
  5777. [0., 0., 1., 0., 1., 0., 0., 0., 0.]])
  5778. >>> # broadcast `value` along multiple axes
  5779. >>> x = paddle.zeros((3, 3, 5))
  5780. >>> value = paddle.ones((1, 3, 1))
  5781. >>> res = paddle.slice_scatter(x, value, axes=[0, 2], starts=[1, 0], ends=[3, 4], strides=[1, 2])
  5782. >>> print(res)
  5783. Tensor(shape=[3, 3, 5], dtype=float32, place=Place(cpu), stop_gradient=True,
  5784. [[[0., 0., 0., 0., 0.],
  5785. [0., 0., 0., 0., 0.],
  5786. [0., 0., 0., 0., 0.]],
  5787. [[1., 0., 1., 0., 0.],
  5788. [1., 0., 1., 0., 0.],
  5789. [1., 0., 1., 0., 0.]],
  5790. [[1., 0., 1., 0., 0.],
  5791. [1., 0., 1., 0., 0.],
  5792. [1., 0., 1., 0., 0.]]])
  5793. """
  5794. none_axes = []
  5795. decrease_axes = []
  5796. dtype = x.dtype
  5797. value = value.astype(dtype)
  5798. if in_dynamic_or_pir_mode():
  5799. return _C_ops.set_value_with_tensor(
  5800. x,
  5801. value,
  5802. starts,
  5803. ends,
  5804. strides,
  5805. axes,
  5806. decrease_axes,
  5807. none_axes,
  5808. )
  5809. else:
  5810. attrs = {
  5811. 'axes': axes,
  5812. 'starts': starts,
  5813. 'ends': ends,
  5814. 'steps': strides,
  5815. 'decrease_axes': decrease_axes,
  5816. 'none_axes': none_axes,
  5817. 'dtype': dtype,
  5818. }
  5819. inputs = {
  5820. 'Input': x,
  5821. 'ValueTensor': value,
  5822. }
  5823. helper = LayerHelper('slice_scatter', **locals())
  5824. output = helper.create_variable_for_type_inference(dtype=x.dtype)
  5825. cur_block = default_main_program().current_block()
  5826. cur_block.append_op(
  5827. type="set_value",
  5828. inputs=inputs,
  5829. outputs={'Out': output},
  5830. attrs=attrs,
  5831. inplace_map={"Input": "Out"},
  5832. )
  5833. return output
  5834. def block_diag(inputs, name=None):
  5835. """
  5836. Create a block diagonal matrix from provided tensors.
  5837. Args:
  5838. inputs (list|tuple): ``inputs`` is a Tensor list or Tensor tuple, one or more tensors with 0, 1, or 2 dimensions.
  5839. name (str, optional): Name for the operation (optional, default is None).
  5840. Returns:
  5841. Tensor, A ``Tensor``. The data type is same as ``inputs``.
  5842. Examples:
  5843. .. code-block:: python
  5844. >>> import paddle
  5845. >>> A = paddle.to_tensor([[4], [3], [2]])
  5846. >>> B = paddle.to_tensor([7, 6, 5])
  5847. >>> C = paddle.to_tensor(1)
  5848. >>> D = paddle.to_tensor([[5, 4, 3], [2, 1, 0]])
  5849. >>> E = paddle.to_tensor([[8, 7], [7, 8]])
  5850. >>> out = paddle.block_diag([A, B, C, D, E])
  5851. >>> print(out)
  5852. Tensor(shape=[9, 10], dtype=int64, place=Place(gpu:0), stop_gradient=True,
  5853. [[4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  5854. [3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  5855. [2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  5856. [0, 7, 6, 5, 0, 0, 0, 0, 0, 0],
  5857. [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
  5858. [0, 0, 0, 0, 0, 5, 4, 3, 0, 0],
  5859. [0, 0, 0, 0, 0, 2, 1, 0, 0, 0],
  5860. [0, 0, 0, 0, 0, 0, 0, 0, 8, 7],
  5861. [0, 0, 0, 0, 0, 0, 0, 0, 7, 8]])
  5862. """
  5863. def to_col_block(arys, i, a):
  5864. return [
  5865. a
  5866. if idx == i
  5867. else paddle.zeros([ary.shape[0], a.shape[1]], dtype=a.dtype)
  5868. for idx, ary in enumerate(arys)
  5869. ]
  5870. def to_2d(ary):
  5871. if ary.ndim == 0:
  5872. return ary.unsqueeze(axis=0).unsqueeze(axis=0)
  5873. if ary.ndim == 1:
  5874. return ary.unsqueeze(axis=0)
  5875. if ary.ndim == 2:
  5876. return ary
  5877. raise ValueError(
  5878. "For 'block_diag', the dimension of each elements in 'inputs' must be 0, 1, or 2, but got "
  5879. f"{ary.ndim}"
  5880. )
  5881. arys = [to_2d(ary) for ary in inputs]
  5882. matrix = [
  5883. paddle.concat(to_col_block(arys, idx, ary), axis=0)
  5884. for idx, ary in enumerate(arys)
  5885. ]
  5886. return paddle.concat(matrix, axis=1)