PageSourceSearch

https://www.oybdooo.top/projects/

html oybdooo.top collected 2026-10-09 22:08:33 UTC 47,591 bytes, 57 lines download raw bytes

1<!doctype html><html lang=en-us dir=ltr data-wc-theme-default=dark><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=generator content="Hugo Blox Builder 0.10.0"><meta name=author content="Boding Ouyang"><meta name=description content><link rel=alternate hreflang=en-us href=https://www.oybdooo.top/projects/><link rel=stylesheet href=/css/themes/cyan.min.css>
2    
3
4  
5  
6  
7  
8  
9  
10  
11    
12      
13        <link rel="stylesheet" href="/css/_entry.3f663481e33504855ea6a15bd254dbc69760c915b964a48eaceb075c5caaad44.css" integrity="sha256-P2Y0geM1BIVepqFb0lTbxpdgyRW5ZKSOrOsHXFyqrUQ=" crossorigin="anonymous">
14      
15    
16  
17
18
19  
20<script src=/js/hb-head.min.01cd73a09512f0fc45bed2c68f9f9a23041c57dafb87c91cf91373611031bd84.js integrity="sha256-Ac1zoJUS8PxFvtLGj5+aIwQcV9r7h8kc+RNzYRAxvYQ=" crossorigin=anonymous></script>
20<link rel=icon type=image/png href=/media/icon_hu_d2801d2ef9a4d96b.png><link rel=apple-touch-icon type=image/png href=/media/icon_hu_6085244891af1178.png><link rel=canonical href=https://www.oybdooo.top/projects/><meta property="twitter:card" content="summary"><meta property="twitter:site" content="@GetResearchDev"><meta property="twitter:creator" content="@GetResearchDev"><meta property="og:site_name" content="Boding Ouyang's Homepage"><meta property="og:url" content="https://www.oybdooo.top/projects/"><meta property="og:title" content="Projects | Boding Ouyang's Homepage"><meta property="og:description" content><meta property="og:image" content="https://www.oybdooo.top/media/icon_hu_3fc173bf4ffcd192.png"><meta property="twitter:image" content="https://www.oybdooo.top/media/icon_hu_3fc173bf4ffcd192.png"><meta property="og:locale" content="en-us"><meta property="article:published_time" content="2024-05-19T00:00:00+00:00"><meta property="article:modified_time" content="2024-05-19T00:00:00+00:00"><title>Projects | Boding Ouyang's Homepage</title><style>@font-face{font-family:inter var;font-style:normal;font-weight:100 900;font-display:swap;src:url(/dist/font/Inter.var.woff2)format(woff2)}</style>
20<script defer src=/js/hugo-blox-en.min.65b31b94cb4f09cfd8f827efdb711400b677b90781e4aee753207d95de698687.js integrity="sha256-ZbMblMtPCc/Y+Cfv23EUALZ3uQeB5K7nUyB9ld5phoc="></script>
20<script>console.log("✓ Alpine.js loading on demand")</script>
20<script src=/dist/lib/alpinejs/cdn.min.e041f1b639d1e6b2fc2736d8d7638a409afcd444a6ec90446f8f4e44fa36f406.js integrity="sha256-4EHxtjnR5rL8JzbY12OKQJr81ESm7JBEb49ORPo29AY=" defer></script>
20<script defer src=/js/hb-search.min.135366008264b9d452ff89aad28374bc7e4b40d2c047098318511786419873b0.js integrity="sha256-E1NmAIJkudRS/4mq0oN0vH5LQNLARwmDGFEXhkGYc7A="></script>
20<link type=text/css rel=stylesheet href=/dist/lib/katex/katex.min.19095127357ed6d29fe0a63a6b000c913a89f7f1963b765dd3715e97c9852e75.css integrity="sha256-GQlRJzV+1tKf4KY6awAMkTqJ9/GWO3Zd03Fel8mFLnU=">
20<script defer src=/dist/lib/katex/katex.min.e8d885505949f3a5f4abdd5dd0d53696bd1371ad26ffbf4f310dcd77c8cdae89.js integrity="sha256-6NiFUFlJ86X0q91d0NU2lr0Tca0m/79PMQ3Nd8jNrok="></script>
20<script defer src=/js/katex-renderer.7bdcf3f3f669a04734c54d2fe7c91a2d07b44e4ec8f1ea72384893db11a740eb.js integrity="sha256-e9zz8/ZpoEc0xU0v58kaLQe0Tk7I8epyOEiT2xGnQOs="></script>
20<script async defer src=https://buttons.github.io/buttons.js></script>
20<script>document.addEventListener("DOMContentLoaded",function(){if(window.location.pathname.startsWith("/post/")&&document.body.classList.add("is-post-page"),window.location.pathname==="/"){var e=document.createElement("video");e.id="bg-video",e.autoplay=!0,e.muted=!0,e.loop=!0,e.playsInline=!0,e.setAttribute("playsinline",""),e.src="/media/neptune-bg.mp4",document.body.prepend(e)}})</script>
20<link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Inter:wght@300;400;500;600;700&display=swap" rel=stylesheet><style>:root{--glow-cyan:0 188 212;--glow-blue:59 130 246;--glow-purple:139 92 246;--glass-bg:rgba(15, 23, 42, 0.6);--glass-border:rgba(0, 188, 212, 0.15);--gradient-primary:linear-gradient(135deg, #06b6d4, #3b82f6, #8b5cf6);--gradient-subtle:linear-gradient(135deg, rgba(6,182,212,0.1), rgba(139,92,246,0.1))}.bio-grid{grid-template-columns:1fr}@media(min-width:768px){.bio-grid{grid-template-columns:30% 1fr}}.dark h1,.dark h2,.dark h3,.dark h4,h1,h2,h3,h4{font-family:space grotesk,system-ui,sans-serif!important;letter-spacing:-.02em}body{font-family:inter,system-ui,-apple-system,sans-serif!important}code,pre,.font-mono{font-family:jetbrains mono,fira code,monospace!important}.dark h2.font-bold.tracking-tight,.dark h3.font-bold.tracking-tight{background:var(--gradient-primary)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.dark .page-body article.prose>h1{background:var(--gradient-primary)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.dark .page-body h3.text-3xl,.dark .page-body .text-3xl.font-bold{background:var(--gradient-primary)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.dark .page-body>.prose h1,.dark .page-body>.prose h2,.dark .page-body article>main h1,.dark .page-body article>main h2{background:var(--gradient-primary);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.dark .page-body article h2 .relative{-webkit-text-fill-color:inherit!important}.dark section:not(:first-child) .text-3xl,.dark section:not(:first-child) .text-2xl{background:var(--gradient-primary);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.dark header{background:rgba(2,6,23,.8)!important;backdrop-filter:blur(24px)saturate(180%)!important;-webkit-backdrop-filter:blur(24px)saturate(180%)!important;border-bottom:1px solid rgba(0,188,212,.12)!important;box-shadow:0 1px 30px rgba(0,188,212,6%)!important}.dark header .navbar-brand{font-family:space grotesk,system-ui,sans-serif!important;font-weight:700!important;letter-spacing:.02em;background:linear-gradient(135deg,#22d3ee,#a78bfa)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important;transition:all .3s ease!important}.dark header .navbar-brand:hover{filter:brightness(1.2);text-shadow:none}.dark .nav-link{color:rgba(203,213,225,.85)!important;font-family:space grotesk,system-ui,sans-serif!important;font-weight:500!important;font-size:.9rem!important;letter-spacing:.04em;text-transform:uppercase;position:relative;padding:.5rem .75rem!important;transition:all .3s cubic-bezier(.4,0,.2,1)!important}.dark .nav-link.active{color:#22d3ee!important}.dark .nav-link.active::after{content:'';position:absolute;bottom:0;left:50%;transform:translateX(-50%);width:60%;height:2px;background:linear-gradient(90deg,transparent,#06b6d4,transparent);border-radius:1px}.dark .nav-link:hover{color:#22d3ee!important;text-shadow:0 0 12px rgba(0,188,212,.5),0 0 24px rgba(0,188,212,.2)!important;-webkit-text-fill-color:#22d3ee!important}.dark .nav-link::before{content:'';position:absolute;bottom:0;left:50%;width:0;height:1px;background:linear-gradient(90deg,#06b6d4,#8b5cf6);transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateX(-50%);box-shadow:0 0 8px rgba(0,188,212,.3)}.dark .nav-link:hover::before{width:80%}.nav-link:hover{color:#0891b2!important;-webkit-text-fill-color:#0891b2!important}.dark header button,.dark header [data-search-toggle]{color:rgba(203,213,225,.7)!important;transition:all .3s ease!important}.dark header button:hover,.dark header [data-search-toggle]:hover{color:#22d3ee!important;filter:drop-shadow(0 0 6px rgba(0,188,212,.4))}#bg-video{position:fixed;top:0;left:0;width:100vw;height:100vh;object-fit:cover;z-index:-2;opacity:.35;pointer-events:none;filter:brightness(.6)saturate(1.2)}.dark body{background:#050510!important}.dark .page-body::before{content:'';position:fixed;top:0;left:0;width:100%;height:100%;background-image:radial-gradient(rgba(0,188,212,6%) 1px,transparent 1px);background-size:30px 30px;pointer-events:none;z-index:-1}.dark .card,.dark [class*=bg-neutral],.dark .rounded-lg[class*=shadow],.dar
20k article.bg-white\/70,.dark .bg-white\/70{background:rgba(15,23,42,.5)!important;backdrop-filter:blur(12px)!important;-webkit-backdrop-filter:blur(12px)!important;border:1px solid rgba(0,188,212,8%)!important;transition:all .4s cubic-bezier(.4,0,.2,1)!important}.dark .card:hover,.dark article.bg-white\/70:hover,.dark .bg-white\/70:hover{border-color:rgba(0,188,212,.25)!important;box-shadow:0 0 30px rgba(0,188,212,8%),0 8px 32px rgba(0,0,0,.3)!important;transform:translateY(-2px)!important}.dark .hb-article-grid-item{background:rgba(15,23,42,.4)!important;border:1px solid rgba(0,188,212,8%)!important;border-radius:12px!important;transition:transform .6s cubic-bezier(.25,.46,.45,.94),border-color .4s ease,box-shadow .4s ease!important;overflow:hidden}.dark .hb-article-grid-item:hover{border-color:rgba(0,188,212,.3)!important;box-shadow:0 0 40px rgba(0,188,212,.1),inset 0 0 20px rgba(0,188,212,2%)!important;transform:scale(1.03)!important}.dark .btn-primary,.dark a[class*=btn][class*=primary],.dark .bg-primary-700{position:relative;overflow:hidden;box-shadow:0 0 15px rgba(0,188,212,.2)!important;transition:all .3s ease!important}.dark .btn-primary:hover,.dark a[class*=btn][class*=primary]:hover{box-shadow:0 0 25px rgba(0,188,212,.4),0 0 60px rgba(0,188,212,.15)!important}.dark a:not([class*=btn]):not(header a):not(footer a){transition:color .3s ease,text-shadow .3s ease}.dark .page-body a:not([class*=btn]):hover{text-shadow:0 0 8px rgba(0,188,212,.3)}.dark .group[class*=from-gray-800][class*=rounded-lg]{border:1px solid rgba(0,188,212,.1)!important;transition:all .4s cubic-bezier(.4,0,.2,1)!important}.dark .group[class*=from-gray-800][class*=rounded-lg]:hover{border-color:rgba(0,188,212,.45)!important;box-shadow:0 0 20px rgba(0,188,212,.1),0 4px 16px rgba(0,0,0,.2)!important}.dark section:first-child .dark{position:relative}.dark section:first-child .dark::after{content:'';position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(0,188,212,.3),rgba(139,92,246,.3),transparent)}.dark .page-body>section+section::before{content:'';display:block;height:1px;margin:0 auto 3rem;max-width:200px;background:linear-gradient(90deg,transparent,rgba(0,188,212,.25),transparent)}@keyframes fadeInUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}.dark section{animation:fadeInUp .6s ease-out both}.dark section:nth-child(2){animation-delay:.1s}.dark section:nth-child(3){animation-delay:.2s}.dark section:nth-child(4){animation-delay:.3s}.dark section:nth-child(5){animation-delay:.4s}.dark section:nth-child(6){animation-delay:.5s}.dark .badge,.dark [class*=tag],.dark span[class*=rounded-full]{border:1px solid rgba(0,188,212,.15)!important;background:rgba(0,188,212,6%)!important;color:rgba(165,243,252,.9)!important;transition:all .3s ease!important}.dark .badge:hover,.dark [class*=tag]:hover,.dark span[class*=rounded-full]:hover{background:rgba(0,188,212,.12)!important;border-color:rgba(0,188,212,.4)!important;color:#22d3ee!important;text-shadow:0 0 8px rgba(0,188,212,.3);box-shadow:0 0 12px rgba(0,188,212,.15)!important;box-shadow:0 0 10px rgba(0,188,212,.15)!important}.dark pre{background:rgba(10,15,30,.8)!important;border:1px solid rgba(0,188,212,.1)!important;border-radius:8px!important}.dark footer{border-top:1px solid rgba(0,188,212,.1)!important;background:rgba(2,6,23,.8)!important}.dark ::-webkit-scrollbar{width:8px}.dark ::-webkit-scrollbar-track{background:#0a0a1a}.dark ::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#06b6d4,#8b5cf6);border-radius:4px}.dark ::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#22d3ee,#a78bfa)}.dark [class*=pagefind],.dark .pagefind-ui{background:rgba(15,23,42,.95)!important;backdrop-filter:blur(20px)!important}.dark ::selection{background:rgba(0,188,212,.25);color:#e2e8f0}.dark section:first-child{position:relative}.dark section:first-child::before{content:'';position:absolute;top:0;right:0;width:150px;height:150px;background:radial-gradient(circle at top right,rgba(0,188,212,8%) 0%,transparent 70%);pointer-events:none;z-index:0}.dark img[class*=avatar],.dark .rounded-full[class*=shadow]{box-shadow:0 0 20px rgba(0,188,212,.15),0 0 40px rgba(139,92,246,8%)!important;border:2px solid rgba(0,188,212,.15)!important;transition:all .4s ease!important}.dark img[class*=avatar]:hover,.dark .rounded-full[class*=shadow]:hover{box-shadow:0 0 30px rgba(0,188,212,.25),0 0 60px rgba(139,92,246,.12)!important;border-color:rgba(0,188,212,.3)!important}@media(min-width:1024px){body.is-post-page .page-body article>main>.prose,body.is-post-page .page-body article>main>.container.prose{font-size:.9375rem;line-height:1.75}}*{transition-property:background-color,border-color,box-shadow;transition-duration:.3s;transition-timing-function:ease}a,button,input,img,video,svg,pre,code{transition-property:none}a{transition:color .3s ease,text-shadow .3s ease!important}:root{--orbit-void:#030712;--orbit-ink:#071120;--orbit-panel:rgba(8, 23, 42, 0.72);--orbit-panel-strong:rgba(9, 28, 52, 0.9);--orbit-line:rgba(116, 220, 255, 0.24);--orbit-line-soft:rgba(116, 220, 255, 0.1);--orbit-cyan:#69dcff;--orbit-cyan-bright:#b7f1ff;--orbit-violet:#a78bfa;--orbit-text:#edf8ff;--orbit-muted:#a8bdcf}.dark body{color:var(--orbit-text);background:#050510!important}#bg-video{opacity:.42;filter:none!important}.dark .page-body{isolation:isolate}.dark .page-body::before{display:none!important}.dark header{position:relative;background:linear-gradient(90deg,rgba(3,8,19,.94),rgba(7,20,37,.9),rgba(3,8,19,.94))!important;border-bottom-color:var(--orbit-line)!important;box-shadow:0 14px 40px rgba(0,0,0,.22),inset 0 -1px rgba(183,241,255,4%)!important}.dark header::after{content:'';position:absolute;bottom:-1px;left:50%;width:min(56vw,44rem);height:1px;transform:translateX(-50%);background:linear-gradient(90deg,transparent,var(--orbit-cyan),var(--orbit-violet),transparent);box-shadow:0 0 18px rgba(105,220,255,.42);pointer-events:none}.dark header .navbar-brand{letter-spacing:.045em;background:linear-gradient(105deg,#dff9ff 10%,var(--orbit-cyan) 52%,#bba8ff 92%)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.dark .nav-link{font-size:1rem!important;font-weight:600!important;letter-spacing:.11em;color:rgba(223,240,249,.72)!important}.dark .nav-link.active,.dark .nav-link:hover{color:var(--orbit-cyan)!important;text-shadow:0 0 14px rgba(105,220,255,.38)!important}.dark #section-resume-biography-3{isolation:isolate;overflow:hidden;padding-top:clamp(2.75rem,3.2vw,3rem)!important}.dark #section-resume-biography-3 .home-section-bg{background:0 0!important}.dark #section-resume-biography-3::before{display:none}.dark #section-resume-biography-3::after{display:none}.dark #section-resume-biography-3 .resume-biography{position:relative;z-index:1;padding-top:clamp(3.25rem,4vw,4rem);padding-bottom:clamp(3.5rem,8vw,6.5rem)}.dark #section-resume-biography-3 .avatar-wrapper{position:relative}.dark #section-resume-biography-3 .avatar-wrapper::after{display:none}.dark #section-resume-biography-3 img.avatar{border-color:#071221!important;box-shadow:none!important;transition:transform .28s ease,filter .28s ease!important}.dark #section-resume-biography-3 .flex.flex-wrap.justify-center.gap-3>a{border-color:transparent!important;background:rgba(4,18,34,.38)!important;box-shadow:none!important;transition:background-color .22s ease,color .22s ease,transform .22s ease,box-shadow .22s ease!important}.dark #section-resume-biography-3 .flex.flex-wrap.justify-center.gap-3>a:hover{border-color:transparent!important;background:rgba(17,57,84,.58)!important}.dark #section-resume-biography-3 a[href*="resume.pdf"]{border:0!important;border-radius:.5rem!important;background:linear-gradient(112deg,rgba(14,83,126,.9) 0%,rgba(14,83,126,.9) 38%,rgba(90,216,255,.94) 50%,rgba(76,127,202,.92) 62%,rgba(14,83,126,.9) 76%)!important;background-size:240% 100%!important;background-position:100%!important;box-shadow:none!important;letter-spacing:.025em;transition:background-position .42s cubic-bezier(.22,.61,.36,1),color .2s ease,transform .22s ease,box-shadow .22s ease!important}@media(hover:hover) and (prefers-reduced-motion:no-preference){.dark .nav-link{transition:color .2s ease,text-shadow .2s ease,opacity .2s ease!important}.dark .nav-link:hover::before{transition-duration:.24s}.dark #section-resume-biography-3 .avatar-wrapper:hover img.avatar{transform:scale(1.018);
20filter:brightness(1.06)saturate(1.08)}.dark #section-resume-biography-3 .flex.flex-wrap.justify-center.gap-3>a:hover{color:var(--orbit-cyan-bright)!important;transform:translateY(-2px)scale(1.035)!important;box-shadow:0 9px 20px rgba(31,182,231,.16)!important}.dark #section-resume-biography-3 a[href*="resume.pdf"]:hover{background-position:0!important;transform:translateY(-1px)!important;box-shadow:0 10px 24px rgba(39,186,236,.2)!important}}.dark .page-body>section+section::before{max-width:min(72vw,48rem);margin:0 auto clamp(2.5rem,5vw,4rem);background:linear-gradient(90deg,transparent,rgba(105,220,255,.18),rgba(167,139,250,.34),rgba(105,220,255,.18),transparent)!important;box-shadow:0 0 16px rgba(105,220,255,.1)}.dark .page-body>section:not(#section-resume-biography-3) .text-3xl.font-bold{letter-spacing:-.035em;text-shadow:0 12px 30px rgba(0,0,0,.24)}.dark .page-body>section:not(#section-resume-biography-3) .text-3xl.font-bold::after{content:'';display:block;width:4.5rem;height:1px;margin:.9rem auto 0;background:linear-gradient(90deg,transparent,var(--orbit-cyan),transparent);box-shadow:0 0 12px rgba(105,220,255,.52)}.dark .page-body [role=article],.dark .page-body .hb-article-grid-item{border:0!important;border-radius:.45rem!important;background:rgba(5,14,28,.42)!important;box-shadow:none!important}.dark .page-body [role=article]>div:first-child{border-bottom:0}.dark .page-body [role=article]:hover,.dark .page-body .hb-article-grid-item:hover{border-color:transparent!important;box-shadow:none!important;transform:none!important}.dark .pub-list-item.view-citation{padding:1rem 1.15rem;border:0;border-radius:0;background:0 0;transition:none}.dark .pub-list-item.view-citation:hover{border-color:transparent;transform:none;background:0 0}.dark .blox-resume-experience ol{border-color:rgba(105,220,255,.24)!important}.dark .blox-resume-experience ol li{margin-bottom:1.45rem;padding:.2rem 0 .55rem;border:0;border-radius:0;background:0 0;box-shadow:none;transition:none}.dark .blox-resume-experience ol li:hover{border-color:transparent;transform:none;background:0 0}.dark .blox-resume-experience li>span.absolute{border:0!important;background:rgba(7,36,58,.74)!important;box-shadow:none!important}.dark .blox-resume-experience li>span.absolute svg{color:var(--orbit-cyan-bright)!important}.dark .blox-resume-experience time{font-family:jetbrains mono,fira code,monospace;font-size:.74rem;letter-spacing:.035em;color:var(--orbit-cyan)!important}.dark .blox-resume-experience li>span:not(.absolute){color:rgba(225,243,250,.76)!important}.dark .page-body .prose,.dark .page-body .text-gray-600,.dark .page-body .text-gray-500{color:var(--orbit-muted)!important}.dark .page-body a:not(header a):not(footer a):hover{color:var(--orbit-cyan-bright)!important}.dark section{animation:none!important}.dark .blox-resume-experience,.dark .blox-resume-experience *,.dark .blox-resume-experience *::before,.dark .blox-resume-experience *::after{transition:none!important;will-change:auto}.dark #section-resume-biography-3 .group[class*=from-gray-800][class*=rounded-lg]{border-color:transparent!important;background:0 0!important;box-shadow:none!important}.dark footer{background:linear-gradient(180deg,rgba(3,9,19,.72),rgba(3,7,18,.98))!important;border-top-color:var(--orbit-line)!important}.dark :focus-visible{outline:2px solid var(--orbit-cyan);outline-offset:3px}@media(max-width:767px){.dark #section-resume-biography-3 .max-w-7xl>div[style*=grid-template-columns]{grid-template-columns:1fr!important;gap:2.25rem!important}.dark #section-resume-biography-3 .resume-biography{padding-top:3.25rem;padding-bottom:4.5rem}.dark #section-resume-biography-3::before{top:-21rem;right:-31rem}.dark .page-body>section+section::before{max-width:68vw}.dark .blox-resume-experience ol li{padding:.9rem .9rem .25rem}}@media(prefers-reduced-motion:reduce){.dark *,.dark *::before,.dark *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}</style></head><body class="dark:bg-hb-dark dark:text-white page-wrapper" id=top><div id=page-bg></div><div class="page-header sticky top-0 z-30"><header id=site-header class=header><nav class="navbar px-3 flex justify-start"><div class="order-0 h-full"><a class=navbar-brand href=/ title="Boding Ouyang's Homepage">Boding Ouyang</a></div>
20<input id=nav-toggle type=checkbox class=hidden>
21<label for=nav-toggle class="order-3 cursor-pointer flex items-center lg:hidden text-dark dark:text-white lg:order-1"><svg id="show-button" class="h-6 fill-current block" viewBox="0 0 20 20"><title>Open Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0V0z"/></svg>
22<svg id="hide-button" class="h-6 fill-current hidden" viewBox="0 0 20 20"><title>Close Menu</title><polygon points="11 9 22 9 22 11 11 11 11 22 9 22 9 11 -2 11 -2 9 9 9 9 -2 11 -2" transform="rotate(45 10 10)"/></svg></label><ul id=nav-menu class="navbar-nav order-3 hidden lg:flex w-full pb-6 lg:order-1 lg:w-auto lg:space-x-2 lg:pb-0 xl:space-x-8 justify-start"><li class=nav-item><a class=nav-link href=/>Bio</a></li><li class=nav-item><a class=nav-link href=/#papers>Papers</a></li><li class=nav-item><a class=nav-link href=/#talks>Talks</a></li><li class=nav-item><a class=nav-link href=/#blogs>Blogs</a></li><li class=nav-item><a class=nav-link href=/experience/>Experience</a></li><li class=nav-item><a class="nav-link active" href=/projects/>Projects</a></li><li class=nav-item><a class=nav-link href=/teaching/>Teaching</a></li></ul><div class="order-1 ml-auto flex items-center md:order-2 lg:ml-0"><button aria-label="toggle search" class="text-black hover:text-primary inline-block px-3 text-xl dark:text-white cursor-pointer" data-search-toggle>
23<svg height="16" width="16" viewBox="0 0 512 512" fill="currentColor"><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8.0 45.3s-32.8 12.5-45.3.0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9.0 208S93.1.0 208 0 416 93.1 416 208zM208 352a144 144 0 100-288 144 144 0 100 288z"/></svg></button></div></nav></header><div x-data=searchModal() x-show=$store.search.open @keydown.escape.window="$store.search.open = false" @keydown.cmd.k.window.prevent="$store.search.open = !$store.search.open" @keydown.ctrl.k.window.prevent="$store.search.open = !$store.search.open" x-cloak class="fixed inset-0 z-[100] bg-black/50 backdrop-blur-sm" style=display:none><div class="absolute inset-0" @click="$store.search.open = false"></div><div class="relative mx-auto mt-[10vh] max-w-3xl" x-show=$store.search.open x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-4 scale-95" x-transition:enter-end="opacity-100 translate-y-0 scale-100" x-transition:leave="transition ease-in duration-150" x-transition:leave-start="opacity-100 translate-y-0 scale-100" x-transition:leave-end="opacity-0 translate-y-4 scale-95"><div class="mx-4 overflow-hidden rounded-2xl bg-white dark:bg-gray-900 shadow-2xl ring-1 ring-gray-900/10 dark:ring-white/10"><div class="border-b border-gray-200 dark:border-gray-800"><div class="flex items-center gap-3 px-4 py-3"><svg class="h-5 w-5 flex-shrink-0 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5A7 7 0 113 10a7 7 0 0114 0z"/></svg>
24<input x-ref=searchInput x-model=query @input="loading = query.trim() !== ''" @input.debounce.300ms=search() type=text placeholder="Search for answers..." class="flex-1 bg-transparent text-lg outline-none text-gray-900 dark:text-gray-100 placeholder-gray-400" autocomplete=off autofocus><div x-show=loading class=flex-shrink-0><svg class="animate-spin h-5 w-5 text-primary-600" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373.0.0 5.373.0 12h4zm2 5.291A7.962 7.962.0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/></svg></div><kbd class="hidden sm:block flex-shrink-0 rounded bg-gray-100 px-2 py-1 text-xs font-semibold text-gray-600 dark:bg-gray-800 dark:text-gray-400">ESC</kbd>
25<button @click="$store.search.open = false" class="flex-shrink-0 rounded-lg p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300 cursor-pointer">
26<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 18 6M6 6l12 12"/></svg></button></div><div x-show="query && availableFilters.length > 0" x-transition class="border-t border-gray-100 dark:border-gray-800 px-4 py-2"><div class="flex flex-wrap gap-2"><button @click="activeFilter = null; search()" :class="activeFilter === null ? 'bg-primary-100 text-primary-700 dark:bg-primary-900 dark:text-primary-300' : 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-400'" class="rounded-full px-3 py-1 text-xs font-medium transition-colors cursor-pointer">
27All Results
28</button>
29<template x-for="filter in availableFilters" :key=filter.filterKey><button @click="activeFilter = filter.filterKey; search()" :class="activeFilter === filter.filterKey ? 'bg-primary-100 text-primary-700 dark:bg-primary-900 dark:text-primary-300' : 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-400'" class="rounded-full px-3 py-1 text-xs font-medium transition-colors cursor-pointer" x-text="filter.label + ' (' + filter.count + ')'"></button></template></div></div></div><div class="max-h-[60vh] overflow-y-auto"><div x-show="!query && results.length === 0" class=p-6></div><div x-show="query && results.length > 0" class="divide-y divide-gray-200 dark:divide-gray-800"><template x-for="(result, index) in results" :key=result.id><a :href=result.url @mouseenter="selectedIndex = index" @click="$store.search.open = false" :class="selectedIndex === index ? 'bg-primary-50 dark:bg-primary-900/20 border-l-2 border-primary-600' : ''" class="block px-6 py-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors group search-result"><div class="flex items-center gap-2 mb-2 flex-wrap"><span x-show="result.filters && result.filters.type" :class="{
30                    'bg-primary-100 text-primary-700 dark:bg-primary-900 dark:text-primary-300': result.filters.type && result.filters.type[0] === 'questions',
31                    'bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300': result.filters.type && result.filters.type[0] === 'faq',
32                    'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300': result.filters.type && result.filters.type[0] === 'docs'
33                  }" class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium" x-text="result.filters.type ? (typeLabels[result.filters.type[0]] || result.filters.type[0]) : ''"></span>
34<span x-show="result.filters && result.filters.category" class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300" x-text="result.filters.category ? result.filters.category[0] : ''"></span>
35<span x-show="result.filters && result.filters.difficulty" class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300" x-text="result.filters.difficulty ? result.filters.difficulty[0] : ''"></span></div><h3 class="text-lg font-semibold text-gray-900 dark:text-white group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors mb-2" x-html="result.meta.title || 'Untitled'"></h3><p class="text-sm text-gray-600 dark:text-gray-400 line-clamp-2" x-html=result.excerpt></p></a></template></div><div x-show="query && loading" class="px-6 py-16 text-center"><div class="inline-flex items-center gap-3"><svg class="animate-spin h-8 w-8 text-primary-600" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373.0.0 5.373.0 12h4zm2 5.291A7.962 7.962.0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/></svg><div class=text-left><p class="text-lg font-medium text-gray-900 dark:text-white">Searching...</p><p class="text-sm text-gray-500 dark:text-gray-400" x-text="'Finding results for &#34;' + query + '&#34;'"></p></div></div></div><div x-show="query && results.length === 0 && !loading && hasSearched" class="px-6 py-12 text-center"><svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
35<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656.0M9 10h.01M15 10h.01M21 12A9 9 0 113 12a9 9 0 0118 0z"/></svg><h3 class="mt-4 text-lg font-semibold text-gray-900 dark:text-white">No results found</h3><p class="mt-2 text-gray-600 dark:text-gray-400" x-text="'No results for &#34;' + query + '&#34;'"></p><button @click="query = ''; $refs.searchInput.focus()" class="mt-4 text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 font-medium">
36Clear search</button></div></div><div class="border-t border-gray-200 dark:border-gray-800 px-4 py-3 bg-gray-50 dark:bg-gray-900/50"><div class="flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><div class="flex items-center gap-3"><span class="flex items-center gap-1"><kbd class="rounded bg-white dark:bg-gray-800 px-1.5 py-0.5 font-mono text-[10px] font-semibold border border-gray-300 dark:border-gray-700">↑↓</kbd>
37Navigate
38</span><span class="flex items-center gap-1"><kbd class="rounded bg-white dark:bg-gray-800 px-1.5 py-0.5 font-mono text-[10px] font-semibold border border-gray-300 dark:border-gray-700">↵</kbd>
39Select
40</span><span x-show="availableFilters.length > 0" class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/></svg>
41<span x-text="availableFilters.length + ' filters'"></span></span></div><a href=https://hugoblox.com target=_blank rel=noopener class="flex items-center gap-1 hover:text-primary-600 dark:hover:text-primary-400 transition-colors"><svg class="h-3 w-3" fill="currentColor" viewBox="0 0 24 24"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
42Powered by Hugo Blox</a></div></div></div></div></div>
42<script>function searchModal(){return{query:"",results:[],loading:!1,hasSearched:!1,selectedIndex:-1,activeFilter:null,availableFilters:[],trendingSearches:'["Search term 1","Search term 2"]',pagefind:null,typeLabels:{questions:'"Questions"',faq:'"FAQ"',docs:'"Documentation"'},async init(){try{this.pagefind=await import("/pagefind/pagefind.js"),await this.pagefind.init(),console.log("✓ Pagefind initialized"),await this.loadFilters()}catch(e){console.error("Failed to initialize Pagefind:",e)}this.$watch("$store.search.open",e=>{e?(this.$nextTick(()=>this.$refs.searchInput?.focus()),document.body.style.overflow="hidden"):(document.body.style.overflow="",this.query="",this.results=[],this.selectedIndex=-1,this.hasSearched=!1)}),window.addEventListener("keydown",e=>{if(!this.$store.search.open||this.results.length===0)return;if(e.key==="ArrowDown")e.preventDefault(),this.selectedIndex=this.selectedIndex<this.results.length-1?this.selectedIndex+1:0,this.scrollToSelected();else if(e.key==="ArrowUp")e.preventDefault(),this.selectedIndex=this.selectedIndex>0?this.selectedIndex-1:this.results.length-1,this.scrollToSelected();else if(e.key==="Enter"&&this.selectedIndex>=0){e.preventDefault();const t=this.results[this.selectedIndex];t&&(window.location.href=t.url,this.$store.search.open=!1)}})},scrollToSelected(){this.$nextTick(()=>{const e=document.querySelector(".search-result:nth-child("+(this.selectedIndex+1)+")");e&&e.scrollIntoView({block:"nearest",behavior:"smooth"})})},async search(){if(!this.query.trim()){this.results=[],this.hasSearched=!1;return}this.loading=!0,this.hasSearched=!1;try{const s={};if(this.activeFilter){const[e,t]=this.activeFilter.split(":");s.filters={[e]:t}}const n=await this.pagefind.search(this.query,s);console.log("Search results:",n),console.log("Search filters:",n.filters),this.results=await Promise.all(n.results.slice(0,10).map(async e=>{const t=await e.data();return console.log("Result data:",t),{id:t.url,url:t.url,meta:t.meta,excerpt:t.excerpt,filters:t.filters||{}}}));const e={type:{},category:{},difficulty:{}};this.results.forEach(t=>{t.filters&&(t.filters.type&&t.filters.type.forEach(t=>{e.type[t]=(e.type[t]||0)+1}),t.filters.category&&t.filters.category.forEach(t=>{e.category[t]=(e.category[t]||0)+1}),t.filters.difficulty&&t.filters.difficulty.forEach(t=>{e.difficulty[t]=(e.difficulty[t]||0)+1}))}
42),console.log("Extracted filter counts from results:",e);const t=[];Object.entries(e.type).forEach(([e,n])=>{t.push({category:"type",value:e,label:this.typeLabels[e]||e.charAt(0).toUpperCase()+e.slice(1),count:n,filterKey:`type:${e}`})}),Object.entries(e.category).forEach(([e,n])=>{t.push({category:"category",value:e,label:e,count:n,filterKey:`category:${e}`})}),Object.entries(e.difficulty).forEach(([e,n])=>{t.push({category:"difficulty",value:e,label:e,count:n,filterKey:`difficulty:${e}`})}),this.availableFilters=t,console.log("Final availableFilters array:",this.availableFilters),this.results.length>0&&(this.selectedIndex=0)}catch(e){console.error("Search error:",e),this.results=[]}finally{this.loading=!1,this.hasSearched=!0}},async loadFilters(){try{const e=await this.pagefind.search("");console.log("Available Pagefind filters:",e.filters);const t=[];e.filters&&e.filters.type&&Object.entries(e.filters.type).forEach(([e,n])=>{t.push({category:"type",value:e,label:e.charAt(0).toUpperCase()+e.slice(1),count:n,filterKey:`type:${e}`})}),e.filters&&e.filters.category&&Object.entries(e.filters.category).forEach(([e,n])=>{t.push({category:"category",value:e,label:e,count:n,filterKey:`category:${e}`})}),e.filters&&e.filters.difficulty&&Object.entries(e.filters.difficulty).forEach(([e,n])=>{t.push({category:"difficulty",value:e,label:e,count:n,filterKey:`difficulty:${e}`})}),this.availableFilters=t,console.log("Processed filters:",this.availableFilters)}catch(e){console.error("Failed to load filters:",e)}}}}document.addEventListener("alpine:init",()=>{Alpine.store("search",{open:!1})})</script>
42<style>[x-cloak]{display:none!important}</style></div><div class=page-body><section id=section-collection class="relative hbb-section blox-collection"><div class=home-section-bg></div><div class="flex flex-col items-center max-w-prose mx-auto gap-3 justify-center px-6 md:px-0"><div class="mb-6 text-3xl font-bold text-gray-900 dark:text-white">Selected Projects</div><p>I enjoy making things. Here are a selection of projects that I have worked on over the years.</p></div><div class="flex flex-col items-center px-6"><div class="container px-8 mx-auto xl:px-5 py-5 lg:py-8 max-w-screen-lg"><div class="grid gap-10 md:grid-cols-3 lg:gap-10"><div class="group bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-2xl ring-1 ring-zinc-900/5 dark:ring-white/10 shadow-lg overflow-hidden transition-all duration-300 ease-out hover:shadow-xl hover:shadow-blue-500/10 hover:-translate-y-2 focus-within:ring-2 focus-within:ring-blue-500/50" role=article aria-labelledby=card-title-ac03e43170b379c086748d4a8c1013b9><div class="relative overflow-hidden aspect-[16/9] bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-zinc-800 dark:to-zinc-900"><a href=https://github.com/pandas-dev/pandas target=_blank rel=noopener class=block><img class="w-full h-full transition-transform duration-500 ease-out group-hover:scale-105 object-contain" srcset="/project/pandas/featured_hu_55571c8781b2e189.webp 400w, /project/pandas/featured_hu_79a257ad0ced174.webp 450w" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" src=/project/pandas/featured_hu_55571c8781b2e189.webp width=450 height=450 loading=lazy decoding=async fetchpriority=high style=position:absolute;height:100%;width:100%;inset:0;color:transparent alt="Pandas featured image"></a><div class="absolute inset-0 pointer-events-none bg-gradient-to-t from-black/10 via-trans
42parent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div></div><div class="p-8 space-y-4"><div class="flex items-center gap-2"><a href=/tags/hugo/><span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-300">Hugo</span></a></div><h3 id=card-title-ac03e43170b379c086748d4a8c1013b9 class="text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors duration-200 leading-tight"><a href=https://github.com/pandas-dev/pandas target=_blank rel=noopener class=hover:underline>Pandas
43<svg style="height:1em" class="inline-flex h-4 w-4 ml-1 align-text-top" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.5 6H5.25A2.25 2.25.0 003 8.25v10.5A2.25 2.25.0 005.25 21h10.5A2.25 2.25.0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"/></svg></a></h3><p class="text-zinc-600 dark:text-zinc-400 text-base leading-relaxed line-clamp-3">Flexible and powerful data analysis / manipulation library for Python, providing labeled data structures.</p><div class="pt-3 border-t border-zinc-100 dark:border-zinc-800"><div class="flex items-center gap-3 text-xs text-zinc-500 dark:text-zinc-500 flex-wrap mb-3"><time class="hidden sm:inline whitespace-nowrap" datetime=2023-10-26>Oct 26, 2023
44</time><span class="hidden sm:inline opacity-40">•</span>
45<span class="hidden sm:inline whitespace-nowrap">1 min read</span></div><div class="pt-2 border-t border-zinc-200/50 dark:border-zinc-700/50"><a href=https://github.com/pandas-dev/pandas target=_blank rel=noopener class="inline-flex items-center gap-2 text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 font-medium text-sm transition-all duration-300 group/link"><span>Read more</span>
46<svg class="w-4 h-4 transition-transform group-hover/link:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0-4 4m4-4H3"/></svg></a></div></div></div></div><div class="group bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-2xl ring-1 ring-zinc-900/5 dark:ring-white/10 shadow-lg overflow-hidden transition-all duration-300 ease-out hover:shadow-xl hover:shadow-blue-500/10 hover:-translate-y-2 focus-within:ring-2 focus-within:ring-blue-500/50" role=article aria-labelledby=card-title-863326fa93a719a784f46e8be65562c1><div class="relative overflow-hidden aspect-[16/9] bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-zinc-800 dark:to-zinc-900"><a href=https://github.com/pytorch/pytorch target=_blank rel=noopener class=block><img class="w-full h-full transition-transform duration-500 ease-out group-hover:scale-105 object-contain" srcset="/project/pytorch/featured_hu_7b72dc4ce8b06ea.webp 400w, /project/pytorch/featured_hu_8afd7fd0988dccef.webp 450w" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" src=/project/pytorch/featured_hu_7b72dc4ce8b06ea.webp width=450 height=450 loading=lazy decoding=async style=position:absolute;height:100%;width:100%;inset:0;color:transparent alt="PyTorch featured image"></a><div class="absolute inset-0 pointer-events-none bg-gradient-to-t from-black/10 via-trans
46parent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div></div><div class="p-8 space-y-4"><div class="flex items-center gap-2"><a href=/tags/hugo/><span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-300">Hugo</span></a></div><h3 id=card-title-863326fa93a719a784f46e8be65562c1 class="text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors duration-200 leading-tight"><a href=https://github.com/pytorch/pytorch target=_blank rel=noopener class=hover:underline>PyTorch
47<svg style="height:1em" class="inline-flex h-4 w-4 ml-1 align-text-top" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.5 6H5.25A2.25 2.25.0 003 8.25v10.5A2.25 2.25.0 005.25 21h10.5A2.25 2.25.0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"/></svg></a></h3><p class="text-zinc-600 dark:text-zinc-400 text-base leading-relaxed line-clamp-3">PyTorch is a Python package that provides tensor computation (like NumPy) with strong GPU acceleration.</p><div class="pt-3 border-t border-zinc-100 dark:border-zinc-800"><div class="flex items-center gap-3 text-xs text-zinc-500 dark:text-zinc-500 flex-wrap mb-3"><time class="hidden sm:inline whitespace-nowrap" datetime=2023-10-26>Oct 26, 2023
48</time><span class="hidden sm:inline opacity-40">•</span>
49<span class="hidden sm:inline whitespace-nowrap">1 min read</span></div><div class="pt-2 border-t border-zinc-200/50 dark:border-zinc-700/50"><a href=https://github.com/pytorch/pytorch target=_blank rel=noopener class="inline-flex items-center gap-2 text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 font-medium text-sm transition-all duration-300 group/link"><span>Read more</span>
50<svg class="w-4 h-4 transition-transform group-hover/link:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0-4 4m4-4H3"/></svg></a></div></div></div></div><div class="group bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-2xl ring-1 ring-zinc-900/5 dark:ring-white/10 shadow-lg overflow-hidden transition-all duration-300 ease-out hover:shadow-xl hover:shadow-blue-500/10 hover:-translate-y-2 focus-within:ring-2 focus-within:ring-blue-500/50" role=article aria-labelledby=card-title-26ae9fc75e3b90f8c2f6ee2b62a63faf><div class="relative overflow-hidden aspect-[16/9] bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-zinc-800 dark:to-zinc-900"><a href=https://github.com/scikit-learn/scikit-learn target=_blank rel=noopener class=block><img class="w-full h-full transition-transform duration-500 ease-out group-hover:scale-105 object-contain" srcset="/project/scikit/featured_hu_ebecb3156f70ea30.webp 400w, /project/scikit/featured_hu_4b8a3ba2530a42f1.webp 450w" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" src=/project/scikit/featured_hu_ebecb3156f70ea30.webp width=450 height=450 loading=lazy decoding=async style=position:absolute;height:100%;width:100%;inset:0;color:transparent alt="scikit-learn featured image"></a><div class="absolute inset-0 pointer-events-none bg-gradient-to-t from-black/10 via-trans
50parent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div></div><div class="p-8 space-y-4"><div class="flex items-center gap-2"><a href=/tags/hugo/><span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-300">Hugo</span></a></div><h3 id=card-title-26ae9fc75e3b90f8c2f6ee2b62a63faf class="text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors duration-200 leading-tight"><a href=https://github.com/scikit-learn/scikit-learn target=_blank rel=noopener class=hover:underline>scikit-learn
51<svg style="height:1em" class="inline-flex h-4 w-4 ml-1 align-text-top" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.5 6H5.25A2.25 2.25.0 003 8.25v10.5A2.25 2.25.0 005.25 21h10.5A2.25 2.25.0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"/></svg></a></h3><p class="text-zinc-600 dark:text-zinc-400 text-base leading-relaxed line-clamp-3">scikit-learn is a Python module for machine learning built on top of SciPy and is distributed under the 3-Clause BSD license.</p><div class="pt-3 border-t border-zinc-100 dark:border-zinc-800"><div class="flex items-center gap-3 text-xs text-zinc-500 dark:text-zinc-500 flex-wrap mb-3"><time class="hidden sm:inline whitespace-nowrap" datetime=2023-10-26>Oct 26, 2023
52</time><span class="hidden sm:inline opacity-40">•</span>
53<span class="hidden sm:inline whitespace-nowrap">1 min read</span></div><div class="pt-2 border-t border-zinc-200/50 dark:border-zinc-700/50"><a href=https://github.com/scikit-learn/scikit-learn target=_blank rel=noopener class="inline-flex items-center gap-2 text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 font-medium text-sm transition-all duration-300 group/link"><span>Read more</span>
54<svg class="w-4 h-4 transition-transform group-hover/link:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0-4 4m4-4H3"/></svg></a></div></div></div></div></div></div></div></section></div><div class=page-footer><footer class="container mx-auto flex flex-col justify-items-center text-sm leading-6 mt-24 mb-4 text-slate-700 dark:text-slate-200"><p class="powered-by text-center">© 2026 Boding Ouyang. This work is licensed under <a href=https://creativecommons.org/licenses/by-nc-nd/4.0 rel="noopener noreferrer" target=_blank>CC BY NC ND 4.0</a></p><p class="powered-by footer-license-icons"><a href=https://creativecommons.org/licenses/by-nc-nd/4.0 rel="noopener noreferrer" target=_blank aria-label="Creative Commons"><i class="fab fa-creative-commons fa-2x" aria-hidden=true></i>
55<i class="fab fa-creative-commons-by fa-2x" aria-hidden=true></i>
56<i class="fab fa-creative-commons-nc fa-2x" aria-hidden=true></i>
57<i class="fab fa-creative-commons-nd fa-2x" aria-hidden=true></i></a></p></footer></div><div id=hb-notification-container class="fixed top-20 right-4 z-[9999] pointer-events-none" aria-live=polite aria-atomic=true></div></body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.