APIs · Patterns · Snippets · Common mistakes
| Type | Key ops | Complexity |
|---|---|---|
list | append, pop, insert, index, sort | append O(1), insert O(n) |
tuple | immutable; hashable → dict key / set elem | O(1) index |
set | add, discard, |, &, -, ^ | O(1) lookup |
dict | get, setdefault, items, keys, values, update | O(1) avg |
str | split, join, strip, replace, find, format, f"" | immutable |
list.sort() in-place; sorted() returns new list. Pass key= not comparator.from collections import Counter, defaultdict, deque, OrderedDict # Counter — frequency map c = Counter("abracadabra") c.most_common(3) # [('a',5),('b',2),('r',2)] c1 + c2; c1 - c2 # arithmetic on counters # defaultdict — no KeyError dd = defaultdict(list) dd['k'].append(1) # auto-creates [] dd2 = defaultdict(int) # dd2['x'] += 1 # deque — O(1) both ends dq = deque(maxlen=3) dq.appendleft(0); dq.popleft() dq.append(4); dq.pop()
import heapq h = []; heapq.heappush(h, 3) smallest = heapq.heappop(h) heapq.heapify(lst) # in-place O(n) # k largest / smallest heapq.nlargest(3, lst) heapq.nsmallest(3, lst, key=lambda x: x[1]) # max-heap trick: negate values heapq.heappush(h, -val)
import bisect a = [1,3,5,7] bisect.bisect_left(a, 5) # 2 — leftmost pos bisect.bisect_right(a, 5) # 3 — rightmost pos bisect.insort(a, 4) # insert + keep sorted
bisect_right(a,hi) - bisect_left(a,lo)import itertools as it it.combinations([1,2,3], 2) # (1,2)(1,3)(2,3) it.permutations([1,2,3], 2) # ordered pairs it.product([0,1], repeat=3) # cartesian product it.chain([1,2],[3,4]) # flatten iterables it.groupby(sorted_lst, key=fn) # MUST be pre-sorted! it.accumulate([1,2,3]) # [1, 3, 6] it.islice(gen, 5) # first 5 from generator
# enumerate, zip, sorted, map, filter, reduce for i, v in enumerate(lst, start=1): ... for a, b in zip(l1, l2): ... # stops at shorter dict(zip(keys, vals)) # dict from two lists sorted(lst, key=lambda x: (-x[1], x[0])) from functools import reduce reduce(lambda a, b: a*b, [1,2,3,4]) # 24 # List / dict / set comprehensions squares = [x**2 for x in range(10) if x%2==0] freq = {k: v for k, v in Counter(lst).items()} flat = [x for sub in matrix for x in sub]
zip truncates to shortest; use zip_longest for padding.# Generator function — lazy, memory-efficient def fib(): a, b = 0, 1 while True: yield a a, b = b, a + b # Generator expression gen = (x**2 for x in range(10**6)) # no memory spike next(gen) # Custom iterator class Range: def __init__(self, n): self.n = n; self.i = 0 def __iter__(self): return self def __next__(self): if self.i >= self.n: raise StopIteration self.i += 1; return self.i - 1
from functools import wraps, lru_cache # Decorator pattern def timer(fn): @wraps(fn) def wrapper(*args, **kwargs): t0 = time.time() result = fn(*args, **kwargs) print(f"{fn.__name__}: {time.time()-t0:.3f}s") return result return wrapper # Memoization @lru_cache(maxsize=None) def dp(n): ... # Context manager from contextlib import contextmanager @contextmanager def managed(): # setup yield # teardown
from dataclasses import dataclass, field from typing import List, Dict, Optional, Tuple, Union @dataclass(order=True) class Point: x: float y: float label: str = "" tags: List[str] = field(default_factory=list) # typing patterns used in interviews def process(data: List[Dict[str, float]]) -> Optional[float]: ... def merge(a: Union[list, tuple]) -> list: ... # Python 3.10+ union shorthand def foo(x: int | None) -> str | int: ...
import json, pickle, csv # JSON with open("f.json") as fh: d = json.load(fh) json.dumps(d, indent=2, default=str) # default handles datetime # Pickle with open("model.pkl", "wb") as f: pickle.dump(obj, f) with open("model.pkl", "rb") as f: obj = pickle.load(f) # CSV import csv reader = csv.DictReader(open("f.csv")) rows = list(reader) # list of dicts
json for serialization by default.| Threading | Multiprocessing | |
|---|---|---|
| GIL | Bound by GIL | Bypasses GIL |
| Use case | I/O-bound | CPU-bound |
| Memory | Shared | Separate |
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor with ProcessPoolExecutor(max_workers=4) as ex: results = list(ex.map(fn, data_chunks))
| # | Pattern | One-liner / Snippet |
|---|---|---|
| 1 | Flatten nested list | [x for sub in lst for x in sub] |
| 2 | Deduplicate preserving order | list(dict.fromkeys(lst)) |
| 3 | Frequency map | Counter(lst) |
| 4 | Group by key | defaultdict(list); dd[k].append(v) |
| 5 | Sliding window | for i in range(len(a)-k+1): window=a[i:i+k] |
| 6 | Two pointers | l,r=0,len(a)-1; while l<r: |
| 7 | Transpose matrix | list(zip(*matrix)) |
| 8 | Chunk list | [lst[i:i+k] for i in range(0,len(lst),k)] |
| 9 | Running max/min | itertools.accumulate(lst, max) |
| 10 | Sort dict by value desc | sorted(d.items(), key=lambda x:-x[1]) |
| 11 | Merge dicts | {**d1, **d2} or d1 | d2 (3.9+) |
| 12 | All unique? | len(lst)==len(set(lst)) |
| 13 | Intersection of lists | list(set(a) & set(b)) |
| 14 | Top-K frequent | Counter(lst).most_common(k) |
| 15 | Binary search | bisect.bisect_left(a, target) |
| 16 | Memoize recursive | @lru_cache(maxsize=None) |
| 17 | Infinite loop with break | sentinel pattern with while True |
| 18 | Unpacking | a, *rest, z = lst |
| 19 | Named tuple | Point = namedtuple('Point',['x','y']) |
| 20 | Default arg mutable trap | use None; assign if arg is None: arg=[] |
| 21 | Conditional expression | x if cond else y |
| 22 | String to list of chars | list(s); back: ''.join(lst) |
| 23 | Count occurrences in string | s.count('a') |
| 24 | Check substring | 'ab' in s |
| 25 | String padding | s.zfill(5); s.ljust(10,'*') |
| 26 | Cartesian product | itertools.product(a, b) |
| 27 | Combinations/Permutations | itertools.combinations(a,2) |
| 28 | Reduce to single value | functools.reduce(op, lst, init) |
| 29 | Batch/chunk generator | islice(iter(lst), batch_size) |
| 30 | Deep copy | import copy; copy.deepcopy(obj) |
| 31 | Priority queue | heapq.heappush(h,(priority,item)) |
| 32 | Parse int safely | int(s) if s.lstrip('-').isdigit() else None |
| 33 | Timing block | time.perf_counter() (not time.time()) |
| 34 | Regex extract | re.findall(r'\d+', s) |
| 35 | Path handling | from pathlib import Path; Path(p).stem |
| 36 | Environment variable | os.environ.get('KEY','default') |
| 37 | Chain iterables | itertools.chain.from_iterable(lists) |
| 38 | Pairwise iterate | zip(lst, lst[1:]) |
| 39 | Singleton pattern | __new__ override or module-level instance |
| 40 | Abstract base class | from abc import ABC, abstractmethod |
| 41 | Dataclass frozen | @dataclass(frozen=True) → hashable |
| 42 | walrus operator | while chunk := f.read(1024): ... |
| 43 | Exception chaining | raise ValueError("msg") from e |
| 44 | Custom exception | class AppError(Exception): pass |
| 45 | Type narrowing | isinstance(x, (int,float)) |
| 46 | Sparse matrix dict | defaultdict(lambda: defaultdict(int)) |
| 47 | Reverse string/list | s[::-1]; lst[::-1] |
| 48 | Power set | [c for r in range(n+1) for c in combinations(lst,r)] |
| 49 | GCD/LCM | math.gcd(a,b); math.lcm(a,b) (3.9+) |
| 50 | Enumerate + unpack | for i,(a,b) in enumerate(zip(l1,l2)): |
np.array([1,2,3], dtype=np.float32) np.zeros((3,4)); np.ones((2,3)); np.eye(4) np.arange(0,10,2) # [0,2,4,6,8] np.linspace(0,1,5) # 5 evenly-spaced np.full((3,3), 7) np.random.seed(42) np.random.randn(3,4) # std normal np.random.randint(0,10,(5,))
a.shape; a.ndim; a.size; a.dtype a.reshape(3,4) # returns view if possible a.reshape(-1, 4) # infer first dim a.flatten() # always copy a.ravel() # view if possible a.T # transpose a[np.newaxis, :] # add axis → (1,n) np.expand_dims(a, axis=0) np.squeeze(a) # remove size-1 dims
reshape may return view; modifying it changes original. Use .copy() to be safe.a[1, 2] # row 1, col 2 a[1:3, :2] # rows 1-2, cols 0-1 # Boolean indexing a[a > 5] # all elements > 5 a[(a > 2) & (a < 8)] # compound condition # Fancy indexing a[[0,2,4]] # select rows by index list a[np.array([0,1]), np.array([2,3])] # (0,2),(1,3) # np.where np.where(a > 0, a, 0) # ReLU np.where(condition) # returns indices
# Examples (3,4) + (4,) → (3,4) # broadcast row (3,1) + (1,4) → (3,4) # outer-product style (1,3,4)+(2,1,4)→ (2,3,4) # Normalize rows: subtract mean per row a -= a.mean(axis=1, keepdims=True)
keepdims=True → shape mismatch.a.sum(axis=0) # sum along rows → col totals a.mean(axis=1) # mean of each row a.max(); a.min() a.std(); a.var() a.cumsum(axis=0) # running sum per col np.argmax(a, axis=1) # index of max per row np.argsort(a)[::-1] # descending sort idx np.unique(a, return_counts=True)
np.vstack([a, b]) # rows (axis=0) np.hstack([a, b]) # cols (axis=1) np.concatenate([a,b], axis=1) np.stack([a,b], axis=0) # new dim np.split(a, 3, axis=0) # equal parts np.array_split(a, 5) # unequal ok
np.dot(a, b) # matrix multiply a @ b # same, cleaner np.linalg.inv(a) np.linalg.det(a) U, S, Vt = np.linalg.svd(a, full_matrices=False) eigenvals, eigenvecs = np.linalg.eig(a) np.linalg.norm(v) # L2 norm np.linalg.norm(v, ord=1) # L1 norm
# Vectorize any function vfn = np.vectorize(my_fn) # slow; just a loop under hood # Prefer ufuncs np.add(a, b); np.multiply(a, b) np.log(a); np.exp(a); np.sqrt(a) # Pairwise distance (no loops) diff = a[:, np.newaxis] - b[np.newaxis, :] dists = np.linalg.norm(diff, axis=-1) # Contiguous memory check a.flags['C_CONTIGUOUS'] # row-major a = np.ascontiguousarray(a)
np.einsum('ij,jk->ik', a, b) = matmul.pd.DataFrame({'a':[1,2], 'b':[3,4]})
pd.read_csv('f.csv', parse_dates=['date'],
dtype={'id': 'int32'},
usecols=['id','val']) # memory tip
pd.read_parquet('f.parquet') # faster for large data
df.to_csv('out.csv', index=False)
df.loc[df['age'] > 25, ['name','age']] # label-based df.iloc[0:5, 2:4] # positional df.query("age > 25 and city == 'BLR'") # readable df.at[idx, 'col'] # scalar: faster than loc df.iat[0, 1] # scalar: faster than iloc
df[cond]['col'] = v → SettingWithCopyWarning. Use df.loc[cond,'col'] = v.# assign — returns new df (chain-friendly) df.assign( bmi = lambda x: x.weight / x.height**2, age_group = lambda x: pd.cut(x.age, bins=[0,18,60,99]) ) # apply — row or col df['col'].apply(lambda x: x*2) df.apply(lambda row: row['a']+row['b'], axis=1) # map — element-wise on Series df['cat'].map({'A':1,'B':2}) df['col'].replace({-1: np.nan}) # replace vals
apply with vectorized ops or np.where / np.select for 10–100× speedup.df.groupby('dept')['salary'].mean() df.groupby(['dept','yr']).agg( mean_sal=('salary','mean'), n=( 'id', 'count') ) # transform — returns same index (for new col) df['dept_mean'] = df.groupby('dept')['sal'].transform('mean') df['rank_in_dept'] = df.groupby('dept')['sal'].transform('rank', ascending=False) # filter groups df.groupby('cat').filter(lambda g: g['val'].mean() > 5)
agg drops NaN by default. Use min_count=1 on sum for explicit NaN propagation.pd.merge(left, right, on='id', how='left') pd.merge(a, b, left_on='aid', right_on='bid') pd.merge(a, b, on='id', how='outer', indicator=True) # concat — stack vertically or horizontally pd.concat([df1, df2], ignore_index=True) # rows pd.concat([df1, df2], axis=1) # cols # self-join: find pairs pd.merge(df, df, on='key', suffixes=('_x','_y'))
# pivot — unique index/columns required df.pivot(index='date', columns='metric', values='val') # pivot_table — handles duplicates with aggfunc pd.pivot_table(df, values='sales', index='region', columns='quarter', aggfunc='sum', fill_value=0) # melt — wide → long df.melt(id_vars=['id'], value_vars=['q1','q2'], var_name='quarter', value_name='sales') # explode — list col → multiple rows df.explode('tags').reset_index(drop=True)
df.isnull().sum() df.dropna(subset=['col'], how='any') df.fillna({'a': 0, 'b': df['b'].median()}) df['col'].fillna(method='ffill') # forward fill df['col'].interpolate('linear') # time-series # Flag + fill pattern df['col_missing'] = df['col'].isnull().astype(int) df['col'].fillna(df['col'].mean(), inplace=True)
# Datetime df['dt'] = pd.to_datetime(df['dt']) df['dt'].dt.year; .dt.month; .dt.dayofweek df['dt'].dt.to_period('M') # monthly period df.resample('W', on='dt')['sales'].sum() # String accessor df['name'].str.lower() df['name'].str.contains('BLR', na=False) df['name'].str.split(',').str[0] df['name'].str.extract(r'(\d+)')
df['ma7'] = df['sales'].rolling(7).mean() df['ema'] = df['sales'].ewm(span=7).mean() df['rolling_std'] = df['sales'].rolling(7).std() df['rank'] = df['score'].rank(method='dense', ascending=False) df['pct_rank'] = df['score'].rank(pct=True)
groupby + rank(method='dense')groupby().cumsum()groupby().pct_change()groupby().nth(0) or sort + drop_duplicates(keep='first')df[df.A > df.B]drop_duplicates(subset='id', keep='last')groupby().nunique()df['col'].shift(1)resample().asfreq().fillna()melt()explode()agg(['mean','std','count'])groupby().quantile([.25,.5,.75])groupby()['col'].idxmax()pd.crosstab(df.a, df.b, normalize='index')df.corr()groupby().apply(lambda x: x.sample(frac=0.1))pd.cut() / pd.qcut()sort_values(['a','b'], ascending=[True,False])df['full'] = df.a + ' ' + df.bdf['col'].apply(json.loads)(df.x - df.x.mean()) / df.x.std() > 3pd.merge_asof()df.stack() / unstack()df.apply(fn, axis=1, result_type='expand')df.pipe(fn1).pipe(fn2)df.isnull().sum() after merge-- ROW_NUMBER / RANK / DENSE_RANK SELECT *, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) rn, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) rnk, DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) dr FROM employees; -- LEAD / LAG — compare to adjacent rows SELECT user_id, event_dt, LAG(event_dt) OVER (PARTITION BY user_id ORDER BY event_dt) prev_dt, LEAD(event_dt) OVER (PARTITION BY user_id ORDER BY event_dt) next_dt FROM events;
-- Running sum SELECT dt, revenue, SUM(revenue) OVER (ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) cum_rev FROM sales; -- 7-day moving average SELECT dt, revenue, AVG(revenue) OVER (ORDER BY dt ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) ma7 FROM sales; -- Partition + running total SUM(sales) OVER (PARTITION BY region ORDER BY dt)
-- CTE WITH ranked AS ( SELECT *, DENSE_RANK() OVER (PARTITION BY dept ORDER BY sal DESC) dr FROM emp ) SELECT * FROM ranked WHERE dr = 2; -- 2nd highest per dept -- Recursive CTE (hierarchy) WITH RECURSIVE tree AS ( SELECT id, parent, name, 1 depth FROM org WHERE parent IS NULL UNION ALL SELECT o.id, o.parent, o.name, t.depth+1 FROM org o JOIN tree t ON o.parent = t.id ) SELECT * FROM tree;
-- CASE WHEN SELECT id, CASE WHEN score >= 90 THEN 'A' WHEN score >= 70 THEN 'B' ELSE 'C' END grade FROM students; -- Manual pivot (conditional aggregation) SELECT user_id, SUM(CASE WHEN product='A' THEN revenue ELSE 0 END) rev_A, SUM(CASE WHEN product='B' THEN revenue ELSE 0 END) rev_B FROM orders GROUP BY user_id;
-- BigQuery / Standard SQL DATE_DIFF(end_dt, start_dt, DAY) DATE_TRUNC(dt, MONTH) -- first day of month FORMAT_DATE('%Y-%m', dt) TIMESTAMP_DIFF(ts2, ts1, MINUTE) EXTRACT(YEAR FROM dt) -- Cohort month DATE_TRUNC(MIN(event_dt) OVER (PARTITION BY user_id), MONTH) cohort_month
DENSE_RANK() = NROW_NUMBER()=1 ORDER BY purchase_dtDATE_TRUNC(first_event, MONTH) + cross joinSUM() OVER (ORDER BY dt)LAG(rev,12) OVER (ORDER BY month)GROUP BY … HAVING COUNT(*) > 1ROW_NUMBER()=1 ORDER BY updated_at DESCSUM(x)/SUM(x) OVER ()RANK() OVER (PARTITION BY …)PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY val)GROUP BY val ORDER BY COUNT DESC LIMIT 1FLOOR(val/10)*10 + GROUP BYSUM(CASE WHEN …)COUNT(col) vs COUNT(*)STRING_AGG(col, ', ') OVER (…)JSON_VALUE(col,'$.field')LEFT JOIN … WHERE right.id IS NULLAVG() OVER (ROWS BETWEEN N-1 PRECEDING AND CURRENT ROW)PERCENT_RANK() OVER (…)WHERE rn <= Ne.manager_id = m.id self-joinCOUNTIF(cond) or SUM(CASE WHEN cond THEN 1 ELSE 0 END)HAVING COUNT(DISTINCT action) = NLAST_VALUE() OVER (… ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)RANGE BETWEEN INTERVAL 29 DAY PRECEDING AND CURRENT ROWQUALIFY ROW_NUMBER()=1CROSS JOIN UNNEST(arr) AS elemIS NOT DISTINCT FROM or COALESCEimport matplotlib.pyplot as plt fig, axes = plt.subplots(2, 3, figsize=(12,6), sharex=True) ax = axes[0][1] ax.plot(x, y, 'o-', color='steelblue', linewidth=2, label='train') ax.scatter(x, y, c=labels, cmap='viridis', alpha=0.6) ax.bar(cats, vals, color=colors) ax.hist(data, bins=30, density=True, alpha=0.7) ax.boxplot(data, vert=True, patch_artist=True) ax.set_xlabel('X'); ax.set_ylabel('Y') ax.set_title('Title') ax.legend(loc='upper right') ax.annotate('peak', xy=(xp, yp), xytext=(xp+1, yp+10), arrowprops=dict(arrowstyle='->')) fig.tight_layout() fig.savefig('plot.png', dpi=150, bbox_inches='tight')
ax.plot() on same axes, ax.legend()imshow(cm, cmap='Blues') + text() annotationsax.barh(features, importances)alphasc=ax.scatter(...,c=vals); fig.colorbar(sc)fig,axes=plt.subplots(1,3,figsize=(15,4))ax.set_yscale('log')ax.plot(fpr,tpr); ax.plot([0,1],[0,1],'--')import seaborn as sns sns.set_theme(style='darkgrid') # Distribution sns.histplot(df, x='val', hue='class', kde=True) sns.kdeplot(df, x='val', fill=True) # Categorical sns.boxplot(data=df, x='cat', y='val', hue='group') sns.violinplot(data=df, x='cat', y='val') sns.countplot(data=df, x='cat', order=df['cat'].value_counts().index) sns.barplot(data=df, x='cat', y='val', ci=95) # + CI bars # Relational sns.scatterplot(data=df, x='a', y='b', hue='label', size='weight') # Multi-panel sns.pairplot(df, hue='target', diag_kind='kde') sns.catplot(data=df, x='x', y='y', col='group', kind='box') # Heatmap sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='coolwarm', vmin=-1, vmax=1)
| Task | Use |
|---|---|
| Correlation matrix | sns.heatmap(df.corr()) |
| Distribution by class | sns.histplot(hue=...) |
| Pair relationships | sns.pairplot() |
| Confidence intervals | sns.barplot(ci=95) |
| Count of categories | sns.countplot(order=...) |
| Custom scatter styling | Matplotlib scatter more flexible |
| Custom subplot layout | Matplotlib fig,axes more control |
from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer from sklearn.ensemble import GradientBoostingClassifier num_pipe = Pipeline([ ('imp', SimpleImputer(strategy='median')), ('sc', StandardScaler()), ]) cat_pipe = Pipeline([ ('imp', SimpleImputer(strategy='most_frequent')), ('ohe', OneHotEncoder(handle_unknown='ignore', sparse_output=False)), ]) pre = ColumnTransformer([ ('num', num_pipe, num_cols), ('cat', cat_pipe, cat_cols), ]) model = Pipeline([ ('pre', pre), ('clf', GradientBoostingClassifier(n_estimators=200)), ]) model.fit(X_train, y_train) model.predict_proba(X_test)[:,1]
# Scalers StandardScaler() # zero mean, unit var MinMaxScaler((0,1)) # range scaling RobustScaler() # robust to outliers # Encoders OrdinalEncoder() LabelEncoder() # for y only; not features OneHotEncoder(drop='first') # Imputers SimpleImputer(strategy='mean'/'median'/'most_frequent'/'constant') KNNImputer(n_neighbors=5) # Feature selection SelectKBest(f_classif, k=10) SelectFromModel(lasso, threshold='mean') VarianceThreshold(threshold=0.0) # remove zero-var
LabelEncoder on features → ordinal relationship implied. Use OHE for categoricals.from sklearn.model_selection import ( cross_val_score, StratifiedKFold, GridSearchCV, RandomizedSearchCV ) cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) scores = cross_val_score(model, X, y, cv=cv, scoring='roc_auc') param_grid = { 'clf__n_estimators': [100,200], 'clf__max_depth': [3,5,None], } gs = GridSearchCV(model, param_grid, cv=5, scoring='roc_auc', n_jobs=-1) gs.fit(X_train, y_train) gs.best_params_; gs.best_score_
from sklearn.metrics import ( accuracy_score, roc_auc_score, f1_score, classification_report, confusion_matrix, mean_squared_error, mean_absolute_error, r2_score, ndcg_score, average_precision_score ) # Classification roc_auc_score(y_test, proba[:,1]) f1_score(y_test, y_pred, average='macro') print(classification_report(y_test, y_pred)) # Regression mean_squared_error(y_test, y_pred, squared=False) # RMSE # Ranking ndcg_score([y_true_ranked], [y_score_ranked], k=10)
import joblib, pickle # joblib — preferred for sklearn (handles numpy arrays) joblib.dump(model, 'model.joblib') model = joblib.load('model.joblib') # Pickle with open('model.pkl','wb') as f: pickle.dump(model, f) # Full pipeline save (best practice) joblib.dump(pipeline, 'full_pipeline.joblib') # Includes preprocessor — no need to save separately
torch.tensor([1,2,3], dtype=torch.float32) torch.zeros(3,4); torch.randn(2,3) torch.arange(0,10,2) t.shape; t.dtype; t.device t.view(-1,4) # like reshape (must be contiguous) t.reshape(-1,4) # safer — copies if needed t.unsqueeze(0); t.squeeze() t.permute(2,0,1) # like numpy transpose t.contiguous() # numpy interop t.numpy() # CPU tensor only torch.from_numpy(arr) # shares memory!
view() requires contiguous tensor. Use reshape() to be safe.x = torch.randn(3, requires_grad=True) y = (x**2).sum() y.backward() x.grad # dy/dx # Disable grad (inference) with torch.no_grad(): out = model(x) # Detach from graph t.detach() t.detach().cpu().numpy() # full convert chain # Zero grads BEFORE backward optimizer.zero_grad() loss.backward() optimizer.step()
zero_grad() → gradients accumulate across batches.import torch.nn as nn class MLP(nn.Module): def __init__(self, in_d, hid, out_d): super().__init__() self.net = nn.Sequential( nn.Linear(in_d, hid), nn.BatchNorm1d(hid), nn.ReLU(), nn.Dropout(0.3), nn.Linear(hid, out_d) ) def forward(self, x): return self.net(x) model = MLP(128, 256, 10) model.parameters() # for optimizer model.state_dict() # weight dict
from torch.utils.data import Dataset, DataLoader class MyDS(Dataset): def __init__(self, X, y): self.X = torch.FloatTensor(X) self.y = torch.LongTensor(y) def __len__(self): return len(self.y) def __getitem__(self, idx): return self.X[idx], self.y[idx] loader = DataLoader(MyDS(X_tr, y_tr), batch_size=64, shuffle=True, num_workers=4, pin_memory=True) # GPU transfer speed
num_workers=4 + pin_memory=True significantly reduces GPU idle time.device = 'cuda' if torch.cuda.is_available() else 'cpu' model = model.to(device) opt = torch.optim.AdamW(model.parameters(), lr=1e-3) crit = nn.CrossEntropyLoss() sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=50) for epoch in range(epochs): model.train() for X_b, y_b in train_loader: X_b, y_b = X_b.to(device), y_b.to(device) opt.zero_grad() loss = crit(model(X_b), y_b) loss.backward() nn.utils.clip_grad_norm_(model.parameters(), 1.0) opt.step() sched.step() model.eval() with torch.no_grad(): val_loss = sum(crit(model(X_b.to(device)), y_b.to(device)) for X_b, y_b in val_loader)
# Save weights only (recommended) torch.save(model.state_dict(), 'model.pth') model.load_state_dict(torch.load('model.pth')) # Save full model (less portable) torch.save(model, 'full.pt') # Checkpoint torch.save({'epoch': epoch, 'model': model.state_dict(), 'opt': opt.state_dict(), 'loss': loss}, 'ckpt.pt') # GPU ops torch.cuda.is_available() torch.cuda.memory_allocated() model.half() # FP16 mixed precision
load_state_dict requires model architecture to already exist. Load weights only after instantiating model.| Layer | Key params | Output shape |
|---|---|---|
nn.Linear(in,out) | in_features, out_features | (B, out) |
nn.Conv2d(in,out,k) | in_ch, out_ch, kernel_size, stride, padding | (B,out_ch,H',W') |
nn.Embedding(V,d) | num_embeddings, embedding_dim | (B,T,d) |
nn.LSTM(d,h) | input_size, hidden_size, num_layers, batch_first | (B,T,h), (h_n,c_n) |
nn.MultiheadAttention | embed_dim, num_heads | (B,T,d) |
nn.BatchNorm1d(d) | num_features | (B,d) |
nn.Dropout(p) | p=drop prob | same shape |
import tensorflow as tf from tensorflow import keras # Sequential model = keras.Sequential([ keras.layers.Dense(256, activation='relu', input_shape=(128,)), keras.layers.BatchNormalization(), keras.layers.Dropout(0.3), keras.layers.Dense(10, activation='softmax'), ]) # Functional (multi-input / skip connections) inp = keras.Input(shape=(128,)) x = keras.layers.Dense(256, activation='relu')(inp) x = keras.layers.Dropout(0.2)(x) out = keras.layers.Dense(1, activation='sigmoid')(x) model = keras.Model(inp, out)
model.compile(
optimizer=keras.optimizers.Adam(lr=1e-3),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
callbacks = [
keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),
keras.callbacks.ReduceLROnPlateau(factor=0.5, patience=3),
keras.callbacks.ModelCheckpoint('best.h5', save_best_only=True),
]
history = model.fit(
X_train, y_train,
epochs=100, batch_size=64,
validation_split=0.2,
callbacks=callbacks
)
model.evaluate(X_test, y_test)
ds = tf.data.Dataset.from_tensor_slices((X, y)) ds = (ds.shuffle(1000) .batch(64) .prefetch(tf.data.AUTOTUNE) # overlap compute + IO .cache()) # cache after first epoch # From generator ds = tf.data.Dataset.from_generator(my_gen, output_signature=( tf.TensorSpec(shape=(128,), dtype=tf.float32), tf.TensorSpec(shape=(), dtype=tf.int32), ))
opt = keras.optimizers.Adam() crit = keras.losses.SparseCategoricalCrossentropy() acc = keras.metrics.SparseCategoricalAccuracy() @tf.function # compile to graph for speed def train_step(X_b, y_b): with tf.GradientTape() as tape: preds = model(X_b, training=True) loss = crit(y_b, preds) grads = tape.gradient(loss, model.trainable_variables) opt.apply_gradients(zip(grads, model.trainable_variables)) acc.update_state(y_b, preds) return loss
# SavedModel format (recommended) model.save('model_dir/') model = keras.models.load_model('model_dir/') # Legacy HDF5 model.save('model.h5') model = keras.models.load_model('model.h5') # Weights only model.save_weights('w.ckpt') model.load_weights('w.ckpt')
get_config() implemented for serialization. Otherwise use custom_objects arg on load.binary_crossentropysparse_categorical_crossentropy (int labels) or categorical_crossentropy (one-hot)mse lossEmbedding(vocab_size, dim, input_length=T)Conv1D(filters,kernel_size,activation='relu')Bidirectional(LSTM(64, return_sequences=True))base.trainable=False, add headtf.keras.mixed_precision.set_global_policy('mixed_float16')np.array / zeros / ones / eye / arange / linspace / random.randn.shape .dtype .reshape(-1,4) .T .flatten() .ravel()a[a>0] / a[[0,2]] / np.where(cond,x,y).sum/.mean/.std axis=0/1 keepdims=Truenp.argmax/.argsort/.unique(return_counts=True)np.vstack/hstack/concatenate/stack/splita @ b / np.linalg.svd/inv/norm/eignp.einsum('ij,jk->ik', a, b)np.log/exp/sqrt/abs/clip/signread_csv/parquet | to_csv(index=False)df.loc[cond, cols] | df.iloc[r,c] | df.query()df.assign(col=lambda x:...) | df.pipe()groupby().agg(name=('col','func'))groupby().transform('mean') — same indexmerge(on, how='left/inner/outer')pivot_table | melt | explodeisnull().sum() | fillna | dropna.str. | .dt. | rolling().mean()rank(method='dense') | cut | qcutROW_NUMBER/RANK/DENSE_RANK OVER (PARTITION BY … ORDER BY …)LAG(col,n,default) / LEAD(col,n)SUM() OVER (ORDER BY dt ROWS BETWEEN …)WITH cte AS (…) SELECT … FROM cteCASE WHEN … THEN … ELSE … ENDDATE_TRUNC(dt,'MONTH') / DATE_DIFF / EXTRACTHAVING COUNT(DISTINCT id) = NLEFT JOIN … WHERE b.id IS NULL (anti-join)STRING_AGG(col,',') OVER (…)QUALIFY ROW_NUMBER()=1Pipeline([('pre',ColumnTransformer),('clf',model)])StandardScaler | MinMaxScaler | RobustScalerSimpleImputer(strategy='median') | KNNImputerOneHotEncoder(handle_unknown='ignore')train_test_split(stratify=y)StratifiedKFold(n_splits=5, shuffle=True)GridSearchCV(cv=5, n_jobs=-1, scoring='roc_auc')roc_auc_score | f1_score(average='macro') | RMSESelectKBest | SelectFromModel | VarianceThresholdjoblib.dump/load for full pipelinetorch.tensor | .to(device) | .detach().cpu().numpy().reshape/.view/.squeeze/.unsqueeze/.permuterequires_grad=True | .backward() | .gradoptimizer.zero_grad() → loss.backward() → step()nn.Sequential | nn.Linear | Conv2d | Embedding | LSTMDataset.__len__/__getitem__ | DataLoader(shuffle,num_workers)model.train() / model.eval()with torch.no_grad(): for inferenceclip_grad_norm_(params, 1.0)torch.save(model.state_dict())Sequential([Dense,BN,Dropout]) | Model(inp,out)model.compile(optimizer,loss,metrics)EarlyStopping(patience=5,restore_best_weights=True)ReduceLROnPlateau | ModelCheckpointmodel.fit(X,y,validation_split=0.2,callbacks=…)tf.data.Dataset.shuffle.batch.prefetch(AUTOTUNE)@tf.function for graph compilationGradientTape().gradient(loss, trainable_vars)model.save('dir/') | load_model('dir/')'relu'/'sigmoid'/'softmax'/'tanh'def f(lst=[]) persists across calls. Use None.default=val.is checks identity; == checks value. x is None always; never x == None.a is b for these ints even if different vars.itertools.zip_longest to pad.0.1+0.2 != 0.3; use math.isclose.nonlocal for enclosing scope; global for module scope.np.nan != np.nan. Use np.isnan().df.loc[].dropna=False (pandas 1.1+).pd.StringDtype() for explicit strings..detach().cpu().numpy() — all three needed.BCEWithLogitsLoss (numerically stable); skip manual sigmoid.model(x, training=True) must pass training flag for BN/Dropout in custom loops.input_signature.loss.item().| API | Library | What it does |
|---|---|---|
np.einsum | NumPy | Flexible tensor contraction; matmul, trace, outer product |
np.broadcast_to | NumPy | Create view with broadcast shape (no copy) |
df.pipe(fn) | Pandas | Apply function to df for clean chaining |
df.assign() | Pandas | Add/modify cols returning new df (chain-safe) |
pd.merge_asof | Pandas | Nearest-key merge for time-series |
df.explode | Pandas | List column → multiple rows |
QUALIFY | BigQuery | Filter on window function without subquery |
SelectFromModel | sklearn | Feature selection using estimator importance |
ColumnTransformer remainder='passthrough' | sklearn | Pass untransformed cols through |
clip_grad_norm_ | PyTorch | Gradient clipping — prevents exploding grads |
pin_memory=True | PyTorch | Faster CPU→GPU tensor transfer |
@tf.function | TF | Compile Python to TF graph for speed |
prefetch(AUTOTUNE) | TF | Overlap preprocessing with compute |
itertools.groupby | Python | Group consecutive elements — MUST pre-sort |
bisect.insort | Python | Insert into sorted list O(n) with binary search |
| Question | Root Cause | Fix |
|---|---|---|
| Why is loss NaN from step 1? | Learning rate too high or log(0) | Reduce LR; add epsilon to log |
| Val loss lower than train loss? | Dropout active at eval; data leakage | Call model.eval(); check splits |
| Model predicts same class always | Class imbalance; saturated sigmoid | Weight classes; check final activation |
| CUDA OOM mid-training | Batch too large; graph accumulation | Reduce batch size; detach in metric loops |
| Gradients all zero | Dead ReLU; wrong loss; detached tensor | Use LeakyReLU; verify loss connectivity |
| Pandas SettingWithCopyWarning | Chained assignment on copy | Use df.loc[cond,'col'] = val |
| Merge explodes row count | Non-unique join keys (many-to-many) | Deduplicate before merge; add validate='m:1' |
| Pipeline score different from manual | Data leakage in manual approach | Trust Pipeline; check manual steps for leakage |
| roc_auc_score ValueError | Only one class in y_test | Ensure stratified split |
| torch.from_numpy edits original array | Shares memory | .copy() numpy array first |
| Accuracy high but model useless | Class imbalance; check baseline | Use F1/AUC; check class distribution |
| Model converges but generalizes poorly | Overfitting; feature leakage | Add dropout; check time-based split |
| apply() returns None | Function returns None implicitly | Ensure explicit return in lambda/func |
| GroupKFold vs StratifiedKFold | User-level data needs GroupKFold to prevent leakage | Use GroupKFold(groups=user_id) |
| SQL returns fewer rows than expected | INNER JOIN drops NULLs | Switch to LEFT JOIN; verify keys |